Skip to content

Instantly share code, notes, and snippets.

@dodheim
Last active March 29, 2018 14:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dodheim/03e93474d2819e8e1872f72e6f01b9c8 to your computer and use it in GitHub Desktop.
Save dodheim/03e93474d2819e8e1872f72e6f01b9c8 to your computer and use it in GitHub Desktop.
is_constexpr_copyable [C++17] (candidate for https://stackoverflow.com/q/43120539)
#include <type_traits>
template<typename T, bool = std::is_default_constructible_v<T> && !std::is_array_v<T>>
struct constexpr_instance;
template<typename T>
struct constexpr_instance<T, true> {
constexpr T operator ()() const { return {}; }
};
namespace detail {
template<typename T>
struct try_copy {
template<
typename V,
typename = std::enable_if_t<std::is_same_v<V, T> && std::is_copy_constructible_v<V>>
>
explicit constexpr try_copy(V const& v) : val_(v) { }
constexpr operator bool () const { return true; }
private:
T val_;
};
template<typename T> struct try_copy<T[]>;
template<> struct try_copy<void>;
template<typename T>
auto can_copy(int) -> std::bool_constant<try_copy<T>(constexpr_instance<T>{}())>;
template<typename T>
auto can_copy(long) -> std::false_type;
}
template<typename T>
using is_constexpr_copyable_t = decltype(detail::can_copy<T>(0));
template<typename T>
is_constexpr_copyable_t<T> constexpr is_constexpr_copyable_v{};
////////////////////////////////////////////////////////////////////////////////
// demo
struct nce_cc_nce_default {
nce_cc_nce_default() noexcept { }
nce_cc_nce_default(nce_cc_nce_default const&) noexcept { }
};
struct nce_cc_ce_default {
constexpr nce_cc_ce_default() noexcept { }
nce_cc_ce_default(nce_cc_ce_default const&) noexcept { }
};
struct nce_cc_no_default {
constexpr nce_cc_no_default(int) noexcept { }
nce_cc_no_default(nce_cc_no_default const&) noexcept { }
};
struct ce_cc_nce_default {
ce_cc_nce_default() noexcept { }
constexpr ce_cc_nce_default(int) noexcept { }
constexpr ce_cc_nce_default(ce_cc_nce_default const&) noexcept { }
};
struct ce_cc_ce_default {
constexpr ce_cc_ce_default() noexcept { }
constexpr ce_cc_ce_default(ce_cc_ce_default const&) noexcept { }
};
struct ce_cc_no_default {
constexpr ce_cc_no_default(int) noexcept { }
constexpr ce_cc_no_default(ce_cc_no_default const&) noexcept { }
};
struct no_cc_nce_default {
no_cc_nce_default() noexcept { }
no_cc_nce_default(no_cc_nce_default const&) = delete;
};
struct no_cc_ce_default {
constexpr no_cc_ce_default() noexcept { }
no_cc_ce_default(no_cc_ce_default const&) = delete;
};
struct no_cc_no_default {
constexpr no_cc_no_default(int) noexcept { }
no_cc_no_default(no_cc_no_default const&) = delete;
};
struct nce_cc_aggregate { nce_cc_ce_default x; };
struct ce_cc_aggregate { ce_cc_ce_default x; };
struct no_cc_aggregate { no_cc_ce_default x; };
// specialization #1
//template<>
//struct constexpr_instance<ce_cc_nce_default> {
// constexpr ce_cc_nce_default operator ()() const { return {0}; }
//};
// specialization #2
//template<>
//struct constexpr_instance<ce_cc_no_default> {
// constexpr ce_cc_no_default operator ()() const { return {0}; }
//};
#include <initializer_list>
#include <string>
#include <string_view>
template<bool, typename>
void is_ce_cc();
template<typename T, bool V = is_constexpr_copyable_v<T>>
inline void print_cc() { is_ce_cc<V, T>(); }
int main() {
print_cc<nce_cc_nce_default>();
print_cc<nce_cc_ce_default>();
print_cc<nce_cc_no_default>();
print_cc<ce_cc_nce_default>(); // false without specialization #1 due to non-constexpr default c'tor
print_cc<ce_cc_ce_default>();
print_cc<ce_cc_no_default>(); // false without specialization #2 due to no default c'tor
print_cc<no_cc_nce_default>();
print_cc<no_cc_ce_default>();
print_cc<no_cc_no_default>();
print_cc<nce_cc_aggregate>();
print_cc<ce_cc_aggregate>();
print_cc<no_cc_aggregate>();
print_cc<std::initializer_list<nce_cc_nce_default>>(); // false for gcc, true for clang (which it should be because of empty lists?)
print_cc<std::initializer_list<ce_cc_nce_default>>();
print_cc<std::initializer_list<ce_cc_ce_default>>();
print_cc<std::initializer_list<nce_cc_aggregate>>(); // oddly, true for both gcc and clang
print_cc<std::initializer_list<ce_cc_aggregate>>();
print_cc<std::initializer_list<no_cc_aggregate>>();
print_cc<int>();
print_cc<int[]>();
print_cc<int[2]>();
print_cc<int&>();
print_cc<int const&>();
print_cc<int&&>();
print_cc<int const&&>();
print_cc<void>();
print_cc<std::string_view>();
print_cc<std::string>();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment