I am trying to get static_assert to help me avoid null pointers in C++11.
The problem seems to be that C++11 require the compiler to compile templates even if they are not instantiated.
I have the following code:
#include <type_traits>
template<typename T, typename... Us>
std::enable_if_t< std::is_constructible<T, Us...>::value == true, T * >
create_if_constructible(Us... args) { return new T(args...); }
template<typename T, typename... Us>
std::enable_if_t< std::is_constructible<T, Us...>::value == false, T * >
create_if_constructible(Us... args) {
static_assert( false, "Class T constructor does not match argument list.");
return nullptr;
}
struct ClassA {
ClassA(int a, string b) {}
};
void foo() {
ClassA *a = create_if_constructible<ClassA>(1, "Hello");
// ClassA *b = create_if_constructible<ClassA>(1, "Hello", "world"); // I want compile time error here.
}
I would like this to compile without error. But the static_assert is compiled and gives me a compile time error.
Only if the the second instantiation of the ClassA is in the code should it give me a compile time error.
create_if_constructible
you get a compiler error if you provide the wrong number of arguments to theClassA
constructor... how's what you're doing leading to "helping [you] avoid null pointers"? – Daelstatic_assert()
inside the "false" version tostatic_assert(std::is_constructible<T, Us...>::value, "Class T constructor does not match argument list.");
it will do what you seem to want.... – Daelstatic_assert
). A workaround is straight forward though -template<class> class always_false : std::false_type {};
andstatic_assert
onalways_false<T>::value
. But I'm also not seeing the point of this code. – Cavorelievostatic_assert
doesn't trigger. It seems intuitive to me that the template should be selected based on signature, then thestatic_assert
kick in. Could you share your understanding of the relevance? Thanks. – Daelenable_if
considered together withis_constructible
- regardless of the value ofis_constructible<...>
, either the return type is invalid (if it's true), or the static assert fires (if it's false). As a result, there's no way you can generate a valid specialization for it. – Cavorelievois_constructible<...>
's use is correct, it doesn't seem to me to be valid for the compiler to deem there to be "no valid specialisation" until instantiation, when the actual compile-time-constant value ofis_constructible
is considered. Under 14.6/8's "Note": If a template is instantiated, errors will be diagnosed according to the other rules in this Standard. Exactly when these errors are diagnosed is a quality of implementation issue." I'd expect this to be one of these instantiation errors – Daelstatic_assert(false, "");
is perfectly valid syntatically. – Cavorelievop = i;
to be diagnosed forint i
andchar *p
, thoughp = i;
is also syntactically valid. Knowing which names are type names allows checking of syntax (and without the ability to check syntax you can't check semantic constraints), but the permission to diagnose is broader. – Cavorelievostd::is_constructible<T, Us...>::value
- being a T-dependent value - required to defer evaluation until instantiation under Two-Phase Name Lookup rules? That could be considered to prohibit the comparison ofenable_if
condition withstatic_assert
condition that leads to the insight that no valid specialisation is possible. (FWIW, I'll point out that it does happen to work on the GCC compiler I tried, though that's just one sample point). – Daelstd::is_constructible<T, Us...>::value
is a dependent name, to be sure, but that doesn't require deferral of checking. – Cavorelievostd::is_constructible<T, Us...>::value
is some special type rather thanbool
, then given sufficiently devious operator overloads you can have a case that would result in a valid specialization. However, a sufficiently smart compiler can ignore this possibility in this case because specializingis_constructible
is UB. Considering the implementation costs, it's unlikely that we'll see a compiler doing this any time soon, but it's always better to write standard-conforming code. – Cavorelievo