3

I am trying to use a pre-C++11 static assert. I found this and this question, but somehow I cant get it running:

#define STATIC_ASSERT(x) \ do { \ const static char dummy[(x)?1:-1] = {0};\ } while(0) struct bar { int value; template<typename T> void setValue(T x); }; template<typename T> void bar::setValue(T x) { STATIC_ASSERT(1==0); } template<> void bar::setValue(int x) { value = x;} int main(){ bar b; int c = 1; b.setValue(c); } 

Compiling this (gcc) results in

error: size of array 'dummy' is negative

I would expect this error to apprear only if I call setValue with anything other than int. I also tried other proposed solutions, but with more or less the same result: The error is there even if I dont instantiate the template with anything other than int. What am I doing wrong?

7
  • Just curious, you know you don't have to use template at all in such case, and simply write it with int type? (It's still interesting question and answer for educational reasons, but I hope your real usage is not as trivial :) ). Commented Oct 12, 2016 at 9:58
  • @Ped7g well, in fact my real usage is as trivial as the example. I want to make absolutely sure that the function is called with parameter of the correct type and no conversion takes place. Whether this is good approach or not I am not yet sure, but thats not a discussion for here. I will put it on codereview... Commented Oct 12, 2016 at 10:00
  • look up the explict keyword Commented Oct 12, 2016 at 10:58
  • @UKMonkey as I understood explicit it allows me to avoid conversions of one particular type (whose code I wrote) but I dont see how this would help to avoid conversions taking place for the parameter of one particular function (e.g. double to int). Moreover explicit is C++11 but I am looking for a C++03 solution Commented Oct 12, 2016 at 13:42
  • explictit works in C98 for constructors; and would allow you to do something like template<class T> X { X(explicit T); &T operator (); } The joy of this is that compiler errors would then say it couldn't convert <type> to <type> if you did something wrong Commented Oct 12, 2016 at 13:46

1 Answer 1

7

If a template is invalid for every instantiation, then the program is ill-formed, no diagnostic required. GCC is therefore perfectly valid in giving you an error here, as the primary template for setValue is invalid no matter what the template argument is.

The way to solve this issue is to make the STATIC_ASSERT expression dependent on a template parameter. One option is to make a dependent_false template class, like this:

template <typename T> struct dependent_false { const static bool value = false; }; template<typename T> void bar::setValue(T x) { STATIC_ASSERT(dependent_false<T>::value); } 
Sign up to request clarification or add additional context in comments.

9 Comments

"If a template is invalid for every instantiation, then the program is ill-formed" even if there is a specialization that is not ill-formed?
ok, got it, but it feels a bit strange that your hack is working. If the compiler would be "clever enough" he could still realize that the template is illformed for any T
That's what two-phase lookup is about. Non-dependent calls are checked in phase 1
@tobi303 What if someone defines a specialization of dependent_false for some T and gives it a ... value = true;? You don't know until instantiation time whether value is still false, or even if it exists at all.
@TartanLlama well, now I am getting confused, what if someone defines a specialization of setValue for some T that is not ill-formed.... that also didnt work. I will have to do so more research to understand this. Thanks for the help
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.