Let me first start off by noting the very similar question here: Detecting constexpr with SFINAE. The difference is that in this question, the detection method works to detect a static method of a class.
I am trying to detect if something can be constexpr copy constructed. I'm quite close, here's what I've got:
template <class T>
constexpr int return_int(T t) { return 0; }
template <class T>
T& unmove(T&& t) { return t; }
template <class ... T>
using void_t = void;
template <class T, class = void>
struct is_constexpr_copy_constructible : std::false_type {};
template <class T>
struct is_constexpr_copy_constructible<T, void_t<
std::integral_constant<int,
return_int(unmove(T{}))
>
>> : std::true_type {};
The logical progression of ideas in this solution is as follows:
- Only constant expression integers can be used for integer template parameters.
- The result of a function call is only considered constexpr if the function is constexpr and all of its parameters are constexpr.
- Passing something by value will entail making a copy.
So I write the function return_int
which gives me a constexpr integer iff a constexpr expression of type having a constexpr copy constructor is passed. unmove
just ensures that the copy constructor rather than the move constructor is called.
The problem is that in order to get an expression in the first place, I have to create my type. I cannot use declval
for this as would be standard in TMP, because this is not an unevaluated context; return_int will actually be evaluated at compile time to compute the type. So I am stuck with a meta-function that detects whether a type is constexpr copy constructible AND constexpr default constructible.
This isn't the end of the world per se as these things tend to overlap, but it's not ideal. Is there any way around this? Fundamentally it boils down to:
- I don't see any way to verify if something is constexpr in an unevaluated context.
- In an evaluated context, I don't see any way to get an instance of the type I'm testing in order to try to make a copy without calling a constructor.
Note that in the similar question I linked, this simply isn't an issue because it is checking static methods, and therefore just doesn't need an instance.
Help?