Implementing is_constexpr_copiable - c++

I tried to implement a value template similar to std::is_constructible with the exception to only be true when the type is copiable in a constexpr environment (i.e. its copy constructor is constexpr qualified). I arrived at the following code:
#include <type_traits>
struct Foo {
constexpr Foo() = default;
constexpr Foo(const Foo&) = default;
};
struct Bar {
constexpr Bar() = default;
Bar(const Bar&);
};
namespace detail {
template <int> using Sink = std::true_type;
template<typename T> constexpr auto constexpr_copiable(int) -> Sink<(T(T()),0)>;
template<typename T> constexpr auto constexpr_copiable(...) -> std::false_type;
}
template<typename T> struct is_constexpr_copiable : decltype(detail::constexpr_copiable<T>(0)){ };
static_assert( is_constexpr_copiable<Foo>::value, "");
static_assert(!is_constexpr_copiable<Bar>::value, "");
Now I ask myself if this is according to standard, since compilers seem to disagree about the output.
https://godbolt.org/g/Aaqoah
Edit (c++17 features):
While implementing the somewhat different is_constexpr_constructible_from, with c++17's new auto non-type template type, I once again found a difference between compilers, when dereferencing a nullptr in a constexpr expression with SFINAE.
#include <type_traits>
struct Foo {
constexpr Foo() = default;
constexpr Foo(const Foo&) = default;
constexpr Foo(const Foo*f):Foo(*f) {};
};
struct Bar {
constexpr Bar() = default;
Bar(const Bar&);
};
namespace detail {
template <int> struct Sink { using type = std::true_type; };
template<typename T, auto... t> constexpr auto constexpr_constructible_from(int) -> typename Sink<(T(t...),0)>::type;
template<typename T, auto... t> constexpr auto constexpr_constructible_from(...) -> std::false_type;
}
template<typename T, auto... t> struct is_constexpr_constructible_from : decltype(detail::constexpr_constructible_from<T, t...>(0)){ };
constexpr Foo foo;
constexpr Bar bar;
static_assert( is_constexpr_constructible_from<Foo, &foo>::value, "");
static_assert(!is_constexpr_constructible_from<Foo, nullptr>::value, "");
static_assert(!is_constexpr_constructible_from<Bar, &bar>::value, "");
int main() {}
https://godbolt.org/g/830SCU
Edit: (April 2018)
Now that both compiler supposedly have support for C++17, I have found the following code to work even better (does not require a default constructor on `T`), but only on clang. Everything is still the same but replace the namespace `detail` with the following:
namespace detail {
template struct Sink {};
template constexpr auto sink(S) -> std::true_type;
template constexpr auto try_copy() -> Sink;
template constexpr auto constexpr_copiable(int) -> decltype(sink(std::declval,0)>>()));
template constexpr auto constexpr_copiable(...) -> std::false_type;
}
https://godbolt.org/g/3fB8jt
This goes very deep into parts of the standard about unevaluated context, and both compilers refuse to allow replacing `const T*` with `const T&` and using `std::declval()` instead of the `nullptr`-cast. Should I get confirmation that clang's behaviour is the accepted standardized behaviour, I will lift this version to an answer as it requires only exactly what has been asked.
Clang accepts some undefined behaviour, dereferencing nullptr, in the evaluation of an unevaluated operand of decltype.

The toughest of the challenges, giving a single function evaluating whether a constexpr constructor from const T& exists for arbitrary T, given here seems hardly possible in C++17. Luckily, we can get a long way without. The reasoning for this goes as follows:
Knowing the problem space
The following restrictions are important for determining if some expression can be evaluated in constexpr content:
To evaluate the copy constructor of T, a value of type const T& is needed. Such a value must refer to an object with active lifetime, i.e. in constexpr context it must refer to some value created in a logically enclosing expression.
In order to create this reference as a result of temporary promotion for arbitrary T as we would need to know and call a constructor, whose arguments could involve virtually arbitrary other expressions whose constexpr-ness we would need to evaluate. This looks like it requires solving the general problem of determining the constexprness of general expressions, as far as I can understand. ¹
¹ Actually, If any constructor with arguments, including the copy constructor, is defined as constexpr, there must be some valid way of constructing a T, either as aggregate initialization or through a constructor. Otherwise, the program would be ill-formed, as can be determined by the requirements of the constexpr specifier §10.1.5.5:
For a constexpr function or constexpr constructor that is neither defaulted nor a template, if no argument values exist such that an invocation of the function or constructor could be an evaluated subexpression of a core constant expression, or, for a constructor, a constant initializer for some object ([basic.start.static]), the program is ill-formed, no diagnostic required.
This might give us a tiny loophole.²
So the expression best be an unevaluated operand §8.2.3.1
In some contexts, unevaluated operands appear ([expr.prim.req], [expr.typeid], [expr.sizeof], [expr.unary.noexcept], [dcl.type.simple], [temp]).
An unevaluated operand is not evaluated
Unevaluated operands are general expressions but they can not be required to be evaluatable at compile time as they are not evaluated at all. Note that the parameters of a template are not part of the unevaluated expressiont itself but rather part of the unqualified id naming the template type. That was part of my original confusion and tries in finding a possible implementation.
Non-type template arguments are required to be constant expressions §8.6 but this property is defined through evaluation (which we have already determined to not be generally possible). §8.6.2
An expression e is a core constant expression unless the evaluation of e, following the rules of the abstract machine, would [highlight by myself] evaluate one of the following expressions:
Using noexpect for the unevaluated context has the same problem: The best discriminator, inferred noexceptness, works only on function calls which can be evaluated as a core-constant expression, so the trick mentionend in this stackoverflow answer does not work.
sizeof has the same problems as decltype. Things may change with concepts.
The newly introduced if constexpr is, sadly, not an expression but a statement with an expression argument. It can therefore not help enforce the constexpr evaluatability of an expression. When the statement is evaluated, so is its expression and we are back at the problem of creating an evaluatable const T&. Discarded statements have not influence on the process at all.
Easy possibilities first
Since the hard part is creating const T&, we simply do it for a small number of common but easily determined possibilities and leave the rest to specialization by extremely special case callers.
namespace detail {
template <int> using Sink = std::true_type;
template<typename T,bool SFINAE=true> struct ConstexprDefault;
template<typename T>
struct ConstexprDefault<T, Sink<(T{}, 0)>::value> { inline static constexpr T instance = {}; };
template<typename T> constexpr auto constexpr_copiable(int) -> Sink<(T{ConstexprDefault<T>::instance}, 0)>;
template<typename T> constexpr auto constexpr_copiable(...) -> std::false_type;
}
template<typename T>
using is_constexpr_copyable_t = decltype(detail::constexpr_copiable<T>(0));
Specializing details::ConstexprDefault must be possible for any class type declaring a constexpr copy constructor, as seen above. Note that the argument does not hold for other compound types which don't have constructors §6.7.2. Arrays, unions, references and enumerations need special considerations.
A 'test suite' with a multitude of types can be found on godbolt. A big thank you goes to reddit user /u/dodheim from whom I have copied it. Additional specializations for the missing compound types are left as an exercise to the reader.
² or What does this leave us with?
Evaluation failure in template arguments is not fatal. SFINAE makes it possible to cover a wide range of possible constructors. The rest of this section is purely theoretical, not nice to compilers and might otherwise be plainly stupid.
It is potentially possible to enumerate many constructors of a type using methods similar to magic_get. Essentially, use a type Ubiq pretending to be convertible to all other types to fake your way through decltype(T{ ubiq<I>()... }) where I is a parameter pack with the currently inspected initializer item count and template<size_t i> Ubiq ubiq() just builds the correct amount of instances. Of course in this case the cast to T would need to be explicitely disallowed.
Why only many? As before, some constexpr constructor will exist but it might have access restrictions. This would give a false positive in our templating machine and lead to infinite search, and at some time the compiler would die :/. Or the constructor might be hidden by an overload which can not be resolved as Ubiq is too general. Same effect, sad compiler and a furious PETC (People for the ethical treatment of compilers™, not a real organization). Actually, access restrictions might be solvable by the fact that those do not apply in template arguments which may allow us to extract a pointer-to-member and [...].
I'll stop here. As far as I can tell, it's tedious and mostly unecessary. Surely, covering possible constructor invocations up 5 arguments will be enough for most use cases. Arbitrary T is very, very hard and we may as well wait for C++20 as template metaprogramming is once again about to change massively.

Related

when to use template non-type classes or plain arguments in constexpr functions

I am very unclear when to use non-type template arguments (C++20) or normal arguments in constexpr functions. It's unclear to me, what the restrictions are and when to switch from pure parameters to non-type template parameters (see Live).
Here an example which illustrates the clunkiness with normal arguments:
template<typename Tuple, typename Pred>
constexpr auto getLambda(Tuple&& tuple, Pred&& pred)
{
return [=](auto I, auto J) {
return pred(std::get<I>(tuple), std::get<J>(tuple));
};
}
template<typename T>
struct A
{
constexpr A(T t) : val(t){};
T val;
};
int main()
{
static constexpr auto t = std::make_tuple(A{10.0}, A{1});
constexpr auto p = [](auto&& a, auto&& b) { return a.val < b.val; };
constexpr auto s = getLambda(t, p);
//constexpr auto b = s(1,0); // that does unfortunately not compile -> go back write differently... :-|||
}
Mostly I first try to use normal arguments like above, and after cumbersome fiddling with compile errors about non-constant expressions, try an approach with template<auto t> (non-type template paramters. Mostly having then two implementations one for each use-case (this seems stupid to me...)
Its sounds to me that modern generic programming with C++20 tends towards compile-time computations using constexpr together with some type-meta-programming.
Could anyone shed some light into this rather new "dark-corner" of C++. I probably misunderstand
when something is not a constant-expression and when it is...
The short version: Use non-type template parameter to set non-type template arguments (more general everywhere, where you need a constant expression) and normal arguments for everything else.
The thing about constexpr functions you always have to keep in mind is that they can also be called at runtime. So every normal argument is not necessarily a constant expression. Hence you cannot use it to provide a non-type template argument (as the I in std::get<I>).
Of course one could argue that when called to calculate a constexpr variable the passed arguments are always constant expressions and could be used as such also inside the function. But it would be unexpected if a constexpr function works at compile time but not anymore at runtime.
One could expect that with the new consteval keyword in C++20, one could use normal arguments to consteval functions in constant expressions, since we know that these arguments have to be constant expressions. But this does not seem to be the case: https://godbolt.org/z/guz7FQ Why this is the case I do not know. But in general I like the seperation between normal variables and non-type template arguments.

Short-circuiting template specialization in std::disjunction

Some Background:
I'm working on putting together a templated class which, as part of template specialization, deduces a type to use for one of its members. This data member needs to support being streamed over the wire, and I'm trying to keep the system as flexible and extensible as possible (with the goal that new variants of the type can be created by modifying some high-level elements of the specialization logic without getting into the guts of the implementation code). Some of the existing usages specialize this data member to be an enum, and the streaming code supports converting this value back and forth to a 32-bit integer for transmission over the wire.
Because an enum could be defined (either implicitly or explicitly) to be backed by a different type -- most dangerous in the case being a 64-bit value -- I'd like to be able enforce that if the resolved type is an enum, its underlying type must be a 32-bit integer (more generally, I just need to enforce that it's a maximum of 32 bits, but I'll be worrying about that complexity once the simpler case is working).
My Attempted Solution:
Stitching together some of the tools provided by type_traits, I came up with the following:
#include <cstdint>
#include <type_traits>
using TestedType = /* Logic for deducing a type */;
constexpr bool nonEnumOrIntBacked =
!std::is_enum_v<TestedType>
|| std::is_same_v<std::underlying_type_t<TestedType>, std::int32_t>;
static_assert(nonEnumOrIntBacked,
"TestedType is an enum backed by something other than a 32-bit integer");
However, when I tried to compile this (using Visual Studio 2017 on the latest update), I was met with the error text
'TestedType': only enumeration type is allowed as an argument to compiler intrinsic type trait '__underlying_type'. Seeing this, I tried an alternative formulation using std::disjunction, which I believe should short-circuit evaluation of templates if an earlier condition evaluates to true (I've ommitted the std qualifiers to make this a bit more readable):
disjunction_v<
negation<is_enum<TestedType>>,
is_same<underlying_type_t<TestedType>, int32_t>
>;
I've also tried wrapping the offending usage of underlying_type_t inside an enable_if predicated on the type being an enum, but didn't have success with that either.
My Question:
Do boolean operators in general (and std::disjunction in particular) not short-circuit evaluation of templates? On the cppreference page for std::disjunction, it states the following (emphasis mine):
Disjunction is short-circuiting: if there is a template type argument Bi with bool(Bi::value) != false, then instantiating disjunction::value does not require the instantiation of Bj::value for j > i
Reading this, I would have expected the ill-formed nature of underlying_type_t<TestedType> for some non-enum type to be irrelevant, since downstream types don't need to be considered once something upstream has been evaluated as true.
If my reading of the spec is incorrect on this point, is there another way to accomplish this check at compile-time, or will I need to add a runtime check to enforce this?
Template arguments are "evaluated" eagerly just like regular arguments. The part causing problems is underyling_type_t, but it's present in full in both versions. You need to delay that part until after you know TestedType is an enum type. This is fairly straightforward with constexpr if (live example):
template<typename T>
constexpr bool nonEnumOrIntBackedImpl() {
if constexpr (std::is_enum_v<T>) {
return std::is_same_v<std::underlying_type_t<T>, std::int32_t>;
} else {
return false;
}
}
template<typename T>
constexpr bool nonEnumOrIntBacked = nonEnumOrIntBackedImpl<T>();
Prior to C++17, one common method is tag dispatching (live example):
template<typename T>
constexpr bool nonEnumOrIntBackedImpl(std::true_type) {
return std::is_same<std::underlying_type_t<T>, std::int32_t>{};
}
template<typename T>
constexpr bool nonEnumOrIntBackedImpl(std::false_type) {
return false;
}
template<typename T>
constexpr bool nonEnumOrIntBacked = nonEnumOrIntBackedImpl<T>(std::is_enum<T>{});
chris explained why the construct failed and gave a solution. But in the spirit of exploiting every single feature of the library, here's how to use the short-circuitry
template<typename T, typename I>
struct is_underlying
{
static constexpr auto value =
std::is_same_v<std::underlying_type_t<T>, I>;
};
using TestedType = int;
constexpr bool nonEnumOrIntBacked =
std::disjunction_v<std::negation<std::is_enum<TestedType>>,
is_underlying<TestedType, std::int32_t>>;
The template needs to be well-formed, but not its value.
An alternative:
template <typename T> struct identity { using type = T; };
bool nonEnumOrIntBacked =
std::is_same<
std::conditional_t<
std::is_enum_v<TestedType>,
std::underlying_type<TestedType>,
identity<void>>::type,
int
>::value
;
with conditional<cont, type1, type2>::type::type :) to delay evaluation.

Is it possible to test whether something is constexpr? [duplicate]

Is it possible to produce a compile-time boolean value based on whether or not a C++11 expression is a constant expression (i.e. constexpr) in C++11? A few questions on SO relate to this, but I don't see a straight answer anywhere.
I once wrote it (EDIT: see below for limitations and explanations). From https://stackoverflow.com/a/10287598/34509 :
template<typename T>
constexpr typename remove_reference<T>::type makeprval(T && t) {
return t;
}
#define isprvalconstexpr(e) noexcept(makeprval(e))
However there are many kinds of constant expressions. The above answer detects prvalue constant expressions.
Explanation
The noexcept(e) expression gives false iff e contains
a potentially evaluated call to a function that does not have a non-throwing exception-specification unless the call is a constant expression,
a potentially evaluated throw expression,
a potentially evaluated throwable form of dynamic_cast or typeid.
Note that the function template makeprval is not declared noexcept, so the call needs to be a constant expression for the first bullet not to apply, and this is what we abuse. We need the other bullets to not apply aswell, but thanksfully, both a throw and a throwable dynamic_cast or typeid aren't allowed in constant expressions aswell, so this is fine.
Limitations
Unfortunately there is a subtle limitation, which may or may not matter for you. The notion of "potentially evaluated" is much more conservative than the limits of what constant expressions apply. So the above noexcept may give false negatives. It will report that some expressions aren't prvalue constant expressions, even though they are. Example:
constexpr int a = (0 ? throw "fooled!" : 42);
constexpr bool atest = isprvalconstexpr((0 ? throw "fooled!" : 42));
In the above atest is false, even though the initialization of a succeeded. That is because for being a constant expression, it suffices that the "evil" non-constant sub-expressions are "never evaluated", even though those evil sub-expressions are potentially-evaluated, formally.
As of 2017, is_constexpr is not possible in C++11. That sounds like an odd thing to say, so let me explain a bit of the history.
First, we added this feature to resolve a defect: http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1129
Johannes Schaub - litb posted a constexpr detection macro that relied on the provision that constant expressions are implicitly noexcept. This worked in C++11, but was never implemented by at least some compilers (for instance, clang). Then, as part of C++17, we evaluated Removing Deprecated Exception Specifications from C++17. As a side-effect of that wording, we accidentally removed that provision. When the Core Working Group discussed adding the provision back in, they realized that there were some serious problems with doing so. You can see the full details in the LLVM bug report. So rather than adding it back in, we decided to consider it a defect against all versions of standard and retroactively removed it.
The effect of this is that there is, to my knowledge, no way to detect whether an expression is usable as a constant expression.
Yes, this is possible. One way to do it (which is valid even with the recent noexcept changes) is to take advantage of the C++11 narrowing conversion rules:
A narrowing conversion is an implicit conversion [...] from an integer type or unscoped enumeration type to an integer type that cannot represent all the values of the original type, except where the source is a constant expression whose value after integral promotions will fit into the target type.
(emphasis mine). List initialization generally disallows narrowing conversions, and when combined with SFINAE we can build gadgets for detecting whether an arbitrary expression is a constant expression:
// p() here could be anything
template<int (*p)()> std::true_type is_constexpr_impl(decltype(int{(p(), 0U)}));
template<int (*p)()> std::false_type is_constexpr_impl(...);
template<int (*p)()> using is_constexpr = decltype(is_constexpr_impl<p>(0));
constexpr int f() { return 0; }
int g() { return 0; }
static_assert(is_constexpr<f>());
static_assert(!is_constexpr<g>());
Live demonstration.
The key here is that int{(expr, 0U)} contains a narrowing conversion from unsigned int to int (and thus is ill-formed), unless expr is a constant expression, in which case the entire expression (expr, 0U) is a constant expression whose evaluated value fits into the type int.
The following is an implementation of is_constexpr for functions, not for arbitrary expressions, for C++11 and C++17. It requires the arguments to the function you want to test to be default constructible, though.
#include <type_traits>
struct A {}; // don't make it too easy, use a UDT
A f1(A a) { return a; } // is_constexpr -> false
constexpr A f2(A a) { return a; } // is_constexpr -> true
// The following turns anything (in our case a value of A) into an int.
// This is necessary because non-type template arguments must be integral
// (likely to change with C++20).
template <class T> constexpr int make_int(T &&) { return 0; }
// Helper to turn some function type (e.g. int(float)) into a function
// pointer type (e.g. int (*)(float)).
template <class T> struct signature_from;
template <class R, class... Args> struct signature_from<R(Args...)> {
using type = R(*)(Args...);
};
// See std::void_t for the idea. This does it for ints instead of types.
template <int...> using void_from_int = void;
// The fallback case: F is not a function pointer to a constexpr function
template <class T, typename signature_from<T>::type F, class = void_from_int<>>
struct is_constexpr {
static constexpr bool value = false;
};
// If void_from_int<make_int(F(Args()...))> doesn't lead to a substitution
// failure, then this is the preferred specialization. In that case F must
// be a function pointer to a constexpr function. If it is not, it could
// not be used in a template argument.
template <class R, class... Args, typename signature_from<R(Args...)>::type F>
struct is_constexpr<R(Args...), F, void_from_int<make_int(F(Args()...))>>
{
static constexpr bool value = true;
};
// proof that it works:
static_assert(!is_constexpr<A(A), f1>::value, "");
static_assert( is_constexpr<A(A), f2>::value, "");
#if __cplusplus >= 201703
// with C++17 the type of the function can be deduced:
template<auto F> struct is_constexpr2 : is_constexpr<std::remove_pointer_t<decltype(F)>, F> {};
static_assert(!is_constexpr2<f1>::value, "");
static_assert( is_constexpr2<f2>::value, "");
#endif
See it in action at https://godbolt.org/g/rdeQme.
C++20 added std::is_constant_evaluated()
This allows checking if a certain expression is a constant evaluated expression, i.e. being evaluated at compile time.
Usage example:
constexpr int foo(int num) {
// below is true in case the condition is being evaluated at compile time
// side note, using: if constexpr (std::is_constant_evaluated())
// would be evaluated always to true, so you should use a simple if!
if (std::is_constant_evaluated()) {
return foo_compiletime(num);
}
else {
return foo_runtime(num);
}
}
int main() {
constexpr auto t1 = foo(6); // reaches foo_compiletime
const auto t2 = foo(6); // reaches foo_compiletime
int n = rand() % 10;
const auto t3 = foo(n); // reaches foo_runtime
auto t4 = foo(6); // unfortunately, reaches foo_runtime
}
The last call in the example above would reach foo_runtime, since the call is not within a constant expression context (the result is not being used as a constant expression, see also this SO answer).
This may lead to undesired pessimization, compared to the case of leaving the decision to the user, who may call:
auto t4 = foo_compiletime(6);
And the compiler is allowed to perform the operations inside foo_compiletime at compile time, if it is declared as constexpr function, or would be obliged to do that if it is declared consteval. However, once we leave the decision to the compiler, we will reach foo_runtime, unless we explicitly direct the compiler to go for foo_compiletime, by taking the result into a const, constexpr or constinit variable. Which then, in a way, omits the value of having one function for both scenarios, if the user is required to help the compiler peek the right path.
Another possible option for the call to be optimized, is:
constexpr auto temp = foo(6); // foo_compiletime
auto t4 = temp;
But again, we require the user to be aware of the inner behavior of foo, which is not exactly what we want to achieve.
See the pessimization in this code.
See more on that in this great blog post on the subject.

Determining if ::std::numeric_limits<T> is safe to instantiate

The class template ::std::numeric_limits<T> may only be instantiated for types T, which can be the return value of functions, since it always defines member functions like static constexpr T min() noexcept { return T(); } (see http://www.cplusplus.com/reference/limits/numeric_limits/ for more information of the non-specialised versions in c++03 or c++11).
If T is i.e. int[2] the instantiation will immediately lead to a compile time error, since int[2] cannot be the return value of a function.
Wrapping ::std::numeric_limits with a safe version is easy - if a way to determine if it is safe to instantiate ::std::numeric_limits is known. This is necessary, since the problematic functions should be accessible if possible.
The obvious (and obviously wrong) way of testing ::std::numeric_limits<T>::is_specialised does not work since it requires instantiation of the problematic class template.
Is there a way to test for safety of instantiation, preferably without enumerating all known bad types? Maybe even a general technique to determine if any class template instantiation is safe?
Concerning the type trait that decides whether a type can be returned for a function, here is how I would go about it:
#include <type_traits>
template<typename T, typename = void>
struct can_be_returned_from_function : std::false_type { };
template<typename T>
struct can_be_returned_from_function<T,
typename std::enable_if<!std::is_abstract<T>::value,
decltype(std::declval<T()>(), (void)0)>::type>
: std::true_type { };
On the other hand, as suggested by Tom Knapen in the comments, you may want to use the std::is_arithmetic standard type trait to determine whether you can specialize numeric_limits for a certain type.
Per paragraph 18.3.2.1/2 of the C++11 Standard on the numeric_limits class template, in fact:
Specializations shall be provided for each arithmetic type, both floating point and integer, including bool.
The member is_specialized shall be true for all such specializations of numeric_limits.
C++11 solutions
Since T only appears as the return type of static member functions in the declarations of the unspecialised ::std::numeric_limits<T> (see C++03 18.2.1.1 and C++11 18.3.2.3), it is enough for this specific problem to ensure that doing so is declaration-safe.
The reason this leads to a compile time error is, that the use of a template-argument may not give rise to an ill-formed construct in the instantiation of the template specialization (C++03 14.3/6, C++11 14.3/6).
For C++11 enabled projects, Andy Prowl's can_be_returned_from_function solution works in all relevant cases: http://ideone.com/SZB2bj , but it is not easily portable to a C++03 environment. It causes an error in when instantiated with an incomplete type ( http://ideone.com/k4Y25z ). The proposed solution will accept incomplete classes instead of causing an error. The current Microsoft compiler (msvc 1700 / VS2012) seems to dislike this solution and fail to compile.
Jonathan Wakely proposed a solution that works by utilizing std::is_convertible<T, T> to determine if T can be the return value of a function. This also eliminates incomplete classes, and is easy to show correct (it is defined in C++11 to do exactly what we want). Execution shows that all cases (arrays, arrays of undefined length, functions, abstract classes) which are known to be problematic are correctly recognized. As a bonus, it also correctly recognizes incomplete classes, which are not allowed as parameters to numeric_limits by the standards (see below), although they seem to cause no problems in practice, as long as no problematic functions are actually called. Test execution: http://ideone.com/zolXpp . Some current compilers (icc 1310 and msvc 1700, which is VS2012's compiler) generate incorrect results with this method.
Tom Knapen's is_arithmetic solution is a very concise C++11 solution, but requires the implementer of a type that specialises numeric_limits to also specialise is_arithmetic. Alternatively, a type that in its base case inherits from is_arithmetic (this type might be called numeric_limits_is_specialised) might be specialised in those cases, since specialising is_abstract might not be semantically correct (e.g. a type that does not specify all basic arithmetic operators, but still is a valid integer-like type).
This whitelisting approach ensures that even incomplete types are handled correctly, unless someone maliciously tries to force compilation errors.
Caveat
As shown by the mixed results, C++11 support remains spotty, even with current compilers, so your mileage with these solutions may vary. A C++03 solution will benefit from more consistent results and the ability to be used in projects that do not wish to switch to C++11.
Towards a robust C++03 solution
Paragraph C++11 8.3.5/8 lists the restrictions for return values:
If the type of a parameter includes a type of the form "pointer to array of unknown bound of T" or "reference to array of unknown bound of T", the program is ill-formed. Functions shall not have a return type of type array or function, although they may have a return type of type pointer or reference to such things. There shall be no arrays of functions, although there can be arrays of pointers to functions.
and goes on in paragraph C++11 8.3.5/9:
Types shall not be defined in return or parameter types. The type of a parameter or the return type for a function definition shall not be an incomplete class type (possibly cv-qualified) unless the function definition is nested within the member-specification for that class (including definitions in nested classes defined within the class).
Which is pretty much the same as paragraph C++03 8.3.5/6:
If the type of a parameter includes a type of the form "pointer to array of unknown bound of T" or "reference to array of unknown bound of T", the program is ill-formed. Functions shall not have a return type of type array or function, although they may have a return type of type pointer or reference to such things. There shall be no arrays of functions, although there can be arrays of pointers to functions. Types shall not
be defined in return or parameter types. The type of a parameter or the return type for a function definition shall not be an incomplete class type (possibly cv-qualified) unless the function definition is nested within the member-specification for that class (including definitions in nested classes defined within the class).
Another kind of problematic types is mentioned identically in C++11 10.4/3 and C++03 10.4/3:
An abstract class shall not be used as a parameter type, as a function return type, or as the type of an explicit conversion. [...]
The problematic functions are not nested within an incomplete class type (except of ::std::numeric_limits<T>, which cannot be their T), so we have four kinds of problematic values of T: Arrays, functions, incomplete class types and abstract class types.
Array Types
template<typename T> struct is_array
{ static const bool value = false; };
template<typename T> struct is_array<T[]>
{ static const bool value = true; };
template<typename T, size_t n> struct is_array<T[n]>
{ static const bool value = true; };
detects the simple case of T being an array type.
Incomplete Class Types
Incomplete class types interestingly do not lead to a compilation error just from instantiation, which means either the tested implementations are more forgiving than the standard, or I am missing something.
C++03 example: http://ideone.com/qZUa1N
C++11 example: http://ideone.com/MkA0Gr
Since I cannot come up with a proper way to detect incomplete types, and even the standard specifies (C++03 17.4.3.6/2 item 5)
In particular, the effects are undefined in the following cases: [...] if an incomplete type (3.9) is used as a template argument when instantiating a template component.
Adding only the following special allowance in C++11 (17.6.4.8/2):
[...] unless specifically allowed for that component
it seems safe to assume that anybody passing incomplete types as template parameters are on their own.
A complete list of the cases where C++11 allows incomplete type parameters is quite short:
declval
unique_ptr
default_delete (C++11 20.7.1.1.1/1: "The class template default_delete serves as the default deleter (destruction policy) for the class template unique_ptr."
shared_ptr
weak_ptr
enable_shared_from_this
Abstract Class & Function Types
Detecting functions is a bit more work than in C++11, since we do not have variadic templates in C++03. However, the above quotes on functions already contain the hint we need; functions may not be elements of arrays.
Paragraph C++11 8.3.4\1 contains the sentence
T is called the array element type; this type shall not be a reference type, the (possibly cv qualified) type void, a function type or an abstract class type.
which is also verbatim in paragraph C++03 8.3.4\1 and will allow us to test if a type is a function type. Detecting (cv) void and reference types is simple:
template<typename T> struct is_reference
{ static const bool value = false; };
template<typename T> struct is_reference<T&>
{ static const bool value = true; };
template<typename T> struct is_void
{ static const bool value = false; };
template<> struct is_void<void>
{ static const bool value = true; };
template<> struct is_void<void const>
{ static const bool value = true; };
template<> struct is_void<void volatile>
{ static const bool value = true; };
template<> struct is_void<void const volatile>
{ static const bool value = true; };
Using this, it is simple to write a meta function for abstract class types and functions:
template<typename T>
class is_abstract_class_or_function
{
typedef char (&Two)[2];
template<typename U> static char test(U(*)[1]);
template<typename U> static Two test(...);
public:
static const bool value =
!is_reference<T>::value &&
!is_void<T>::value &&
(sizeof(test<T>(0)) == sizeof(Two));
};
Note that the following meta function may be used to distinguish between the two, should one wish to make a distinct is_function and is_abstract_class
template<typename T>
class is_class
{
typedef char (&Two)[2];
template<typename U> static char test(int (U::*));
template<typename U> static Two test(...);
public:
static const bool value = (sizeof(test<T>(0)) == sizeof(char));
};
Solution
Combining all of the previous work, we can construct the is_returnable meta function:
template<typename T> struct is_returnable
{ static const bool value = !is_array<T>::value && !is_abstract_class_or_function<T>::value; };
Execution for C++03 (gcc 4.3.2): http://ideone.com/thuqXY
Execution for C++03 (gcc 4.7.2): http://ideone.com/OR4Swf
Execution for C++11 (gcc 4.7.2): http://ideone.com/zIu7GJ
As expected, all test cases except for the incomplete class yield the correct answer.
In addition to the above test runs, this version is tested (with the exact same test program) to yield the same results w/o warnings or errors on:
MSVC 1700 (VS2012 with and w/o XP profile), 1600 (VS2010), 1500 (VS2008)
ICC Win 1310
GCC (C++03 and C++11/C++0x mode) 4.4.7, 4.6.4, 4.8.0 and a 4.9 snapshot
Restrictions for either case
Note that, while this approach in either version works for any numeric_limits implementation that does not extend upon the implementation shown in the standard, it is by no means a solution to the general problem, and in fact may theoretically lead to problems with weird but standard compliant implementations (e.g. ones which add private members).
Incomplete classes remain a problem, but it seems silly to require higher robustness goals than the standard library itself.
std::is_convertible<T, T>::value will tell you if a type can be returned from a function.
is_convertible<T1, T2> is defined in terms of a function returning a T2 converted from an expression of type T1.
#include <limits>
#include <type_traits>
struct Incomplete;
struct Abstract { virtual void f() = 0; };
template<typename T>
using is_numeric_limits_safe = std::is_convertible<T, T>;
int main()
{
static_assert(!is_numeric_limits_safe<Incomplete>::value, "Incomplete");
static_assert(!is_numeric_limits_safe<Abstract>::value, "Abstract");
static_assert(!is_numeric_limits_safe<int[2]>::value, "int[2]");
}
This might not be exactly what you want, because it is safe to instantiate std::numeric_limits<Incomplete> as long as you don't call any of the functions that return by value. It's not possible to instantiate std::numeric_limits<int[2]> though.
Here's a better test (using SFINAE) which gives is_numeric_limits_safe<Incomplete>::value==true
template<typename T>
class is_numeric_limits_unsafe
{
struct mu { };
template<typename U>
static U test(int);
template<typename U>
static mu test(...);
public:
typedef std::is_same<decltype(test<T>(0)), mu> type;
};
template<typename T>
struct is_numeric_limits_safe
: std::integral_constant<bool, !is_numeric_limits_unsafe<T>::type::value>
{ };

Is is_constexpr possible in C++11?

Is it possible to produce a compile-time boolean value based on whether or not a C++11 expression is a constant expression (i.e. constexpr) in C++11? A few questions on SO relate to this, but I don't see a straight answer anywhere.
I once wrote it (EDIT: see below for limitations and explanations). From https://stackoverflow.com/a/10287598/34509 :
template<typename T>
constexpr typename remove_reference<T>::type makeprval(T && t) {
return t;
}
#define isprvalconstexpr(e) noexcept(makeprval(e))
However there are many kinds of constant expressions. The above answer detects prvalue constant expressions.
Explanation
The noexcept(e) expression gives false iff e contains
a potentially evaluated call to a function that does not have a non-throwing exception-specification unless the call is a constant expression,
a potentially evaluated throw expression,
a potentially evaluated throwable form of dynamic_cast or typeid.
Note that the function template makeprval is not declared noexcept, so the call needs to be a constant expression for the first bullet not to apply, and this is what we abuse. We need the other bullets to not apply aswell, but thanksfully, both a throw and a throwable dynamic_cast or typeid aren't allowed in constant expressions aswell, so this is fine.
Limitations
Unfortunately there is a subtle limitation, which may or may not matter for you. The notion of "potentially evaluated" is much more conservative than the limits of what constant expressions apply. So the above noexcept may give false negatives. It will report that some expressions aren't prvalue constant expressions, even though they are. Example:
constexpr int a = (0 ? throw "fooled!" : 42);
constexpr bool atest = isprvalconstexpr((0 ? throw "fooled!" : 42));
In the above atest is false, even though the initialization of a succeeded. That is because for being a constant expression, it suffices that the "evil" non-constant sub-expressions are "never evaluated", even though those evil sub-expressions are potentially-evaluated, formally.
As of 2017, is_constexpr is not possible in C++11. That sounds like an odd thing to say, so let me explain a bit of the history.
First, we added this feature to resolve a defect: http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1129
Johannes Schaub - litb posted a constexpr detection macro that relied on the provision that constant expressions are implicitly noexcept. This worked in C++11, but was never implemented by at least some compilers (for instance, clang). Then, as part of C++17, we evaluated Removing Deprecated Exception Specifications from C++17. As a side-effect of that wording, we accidentally removed that provision. When the Core Working Group discussed adding the provision back in, they realized that there were some serious problems with doing so. You can see the full details in the LLVM bug report. So rather than adding it back in, we decided to consider it a defect against all versions of standard and retroactively removed it.
The effect of this is that there is, to my knowledge, no way to detect whether an expression is usable as a constant expression.
Yes, this is possible. One way to do it (which is valid even with the recent noexcept changes) is to take advantage of the C++11 narrowing conversion rules:
A narrowing conversion is an implicit conversion [...] from an integer type or unscoped enumeration type to an integer type that cannot represent all the values of the original type, except where the source is a constant expression whose value after integral promotions will fit into the target type.
(emphasis mine). List initialization generally disallows narrowing conversions, and when combined with SFINAE we can build gadgets for detecting whether an arbitrary expression is a constant expression:
// p() here could be anything
template<int (*p)()> std::true_type is_constexpr_impl(decltype(int{(p(), 0U)}));
template<int (*p)()> std::false_type is_constexpr_impl(...);
template<int (*p)()> using is_constexpr = decltype(is_constexpr_impl<p>(0));
constexpr int f() { return 0; }
int g() { return 0; }
static_assert(is_constexpr<f>());
static_assert(!is_constexpr<g>());
Live demonstration.
The key here is that int{(expr, 0U)} contains a narrowing conversion from unsigned int to int (and thus is ill-formed), unless expr is a constant expression, in which case the entire expression (expr, 0U) is a constant expression whose evaluated value fits into the type int.
The following is an implementation of is_constexpr for functions, not for arbitrary expressions, for C++11 and C++17. It requires the arguments to the function you want to test to be default constructible, though.
#include <type_traits>
struct A {}; // don't make it too easy, use a UDT
A f1(A a) { return a; } // is_constexpr -> false
constexpr A f2(A a) { return a; } // is_constexpr -> true
// The following turns anything (in our case a value of A) into an int.
// This is necessary because non-type template arguments must be integral
// (likely to change with C++20).
template <class T> constexpr int make_int(T &&) { return 0; }
// Helper to turn some function type (e.g. int(float)) into a function
// pointer type (e.g. int (*)(float)).
template <class T> struct signature_from;
template <class R, class... Args> struct signature_from<R(Args...)> {
using type = R(*)(Args...);
};
// See std::void_t for the idea. This does it for ints instead of types.
template <int...> using void_from_int = void;
// The fallback case: F is not a function pointer to a constexpr function
template <class T, typename signature_from<T>::type F, class = void_from_int<>>
struct is_constexpr {
static constexpr bool value = false;
};
// If void_from_int<make_int(F(Args()...))> doesn't lead to a substitution
// failure, then this is the preferred specialization. In that case F must
// be a function pointer to a constexpr function. If it is not, it could
// not be used in a template argument.
template <class R, class... Args, typename signature_from<R(Args...)>::type F>
struct is_constexpr<R(Args...), F, void_from_int<make_int(F(Args()...))>>
{
static constexpr bool value = true;
};
// proof that it works:
static_assert(!is_constexpr<A(A), f1>::value, "");
static_assert( is_constexpr<A(A), f2>::value, "");
#if __cplusplus >= 201703
// with C++17 the type of the function can be deduced:
template<auto F> struct is_constexpr2 : is_constexpr<std::remove_pointer_t<decltype(F)>, F> {};
static_assert(!is_constexpr2<f1>::value, "");
static_assert( is_constexpr2<f2>::value, "");
#endif
See it in action at https://godbolt.org/g/rdeQme.
C++20 added std::is_constant_evaluated()
This allows checking if a certain expression is a constant evaluated expression, i.e. being evaluated at compile time.
Usage example:
constexpr int foo(int num) {
// below is true in case the condition is being evaluated at compile time
// side note, using: if constexpr (std::is_constant_evaluated())
// would be evaluated always to true, so you should use a simple if!
if (std::is_constant_evaluated()) {
return foo_compiletime(num);
}
else {
return foo_runtime(num);
}
}
int main() {
constexpr auto t1 = foo(6); // reaches foo_compiletime
const auto t2 = foo(6); // reaches foo_compiletime
int n = rand() % 10;
const auto t3 = foo(n); // reaches foo_runtime
auto t4 = foo(6); // unfortunately, reaches foo_runtime
}
The last call in the example above would reach foo_runtime, since the call is not within a constant expression context (the result is not being used as a constant expression, see also this SO answer).
This may lead to undesired pessimization, compared to the case of leaving the decision to the user, who may call:
auto t4 = foo_compiletime(6);
And the compiler is allowed to perform the operations inside foo_compiletime at compile time, if it is declared as constexpr function, or would be obliged to do that if it is declared consteval. However, once we leave the decision to the compiler, we will reach foo_runtime, unless we explicitly direct the compiler to go for foo_compiletime, by taking the result into a const, constexpr or constinit variable. Which then, in a way, omits the value of having one function for both scenarios, if the user is required to help the compiler peek the right path.
Another possible option for the call to be optimized, is:
constexpr auto temp = foo(6); // foo_compiletime
auto t4 = temp;
But again, we require the user to be aware of the inner behavior of foo, which is not exactly what we want to achieve.
See the pessimization in this code.
See more on that in this great blog post on the subject.