Reputation: 1292
Assuming these two helper structs:
struct A { static constexpr bool Value = false; };
template <bool DEFERRED> struct B { static_assert(DEFERRED, "Failed"); };
And the follow class that uses it:
class XYZ {
public:
template <class X = A, class Y = B<X::Value>> int SomeFunction() {...}
....
int main() {
XYZ xyz;
xyz.SomeFunction();
}
I don't see why the static assertion is not called, since template boolean DEFERRED should evaluate to false. However when I instantiate template type Y inside the function body, the static assertion is called.
Is there a way to trigger the static_assert evaluation without instantiating template type Y? (Or an easier / smarter way)
EDIT: I should mention I'm using GCC 5.0
Thank you.
Upvotes: 2
Views: 856
Reputation: 1292
I think my question was misunderstood. My issue was that I was expecting the compiler to evaluate the body when the type was instantiated, not when it was used in a declaration. Either way I resolved my issue by doing the following (Using the boilerplate code):
template <bool DEFERRED> struct B {
static constexpr bool Proxy = DEFERRED;
static_assert(Proxy , "Failed");
};
template <class X = A, bool T = B<X::Value>::Proxy> int SomeFunction() {...}
Which forced the compiler to evaluate the body and trigger any static assertions.
Upvotes: 1
Reputation: 12811
since template boolean DEFERRED should evaluate to false (in your question)....
This is because of the constexpr
in struct A
.
constexpr
specifier makes it possible to evaluate the bool
value at compile time
Take out constexpr
and build, you will notice the difference.
Why your static_assert
is not working:
static_assert
expects a bool_constexpr
.
DEFERRED
is just bool and the value is known inside the template class body only if we instantiate.
Try with below code, I added another bool constexpr
inside struct B
naming test
. And pass that variable to static_assert
. Now your static_assert
works.
//g++ 5.4.0
#include <iostream>
struct A { static constexpr bool Value = false; };
template <bool DEFERRED> struct B {
static constexpr bool test = false;
static_assert(test, "Failed");
};
class XYZ {
public:
template <class X = A, class Y = B<X::Value>> int SomeFunction()
{
return 0;
}
};
int main()
{
XYZ xyz;
xyz.SomeFunction();
}
You will notice the output:
source_file.cpp:8:6: error: static assertion failed: Failed
static_assert(test, "Failed");
^
Now change the test
value in struct B
to true
.
It works, no errors.
There is another scenario, assign DEFERRED
to test
variable as shown below:
template <bool DEFERRED> struct B {
static constexpr bool test = DEFERRED;
static_assert(test, "Failed");
};
The above said static_assert
works only if you instantiate in main(), something like below.
B<false> b;
Upvotes: 1
Reputation: 409442
You can see a class as a blueprint for an object, and you can see a template as a blueprint for a class.
A template is just a template, it is not a class until you instantiate the template into a class, which you don't do until the declaration of the xyz
variable.
Upvotes: 1