Last active
March 29, 2018 14:27
-
-
Save dodheim/03e93474d2819e8e1872f72e6f01b9c8 to your computer and use it in GitHub Desktop.
is_constexpr_copyable [C++17] (candidate for https://stackoverflow.com/q/43120539)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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