4

Is it possible to specialize this template declaration:

template <class TYPE, class... ARGS> TYPE Foo(ARGS... args) { 
    static_assert(false);
}

I tried a few things such as:

template <> int Foo<int>(float args) {
    return 42;
}

...but I always hit the static assert when I try to use it as such:

auto value = Foo<int>(1.5f);

What's the correct syntax?

Erunehtar
  • 1,583
  • 1
  • 19
  • 38
  • Maybe it's just that your compiler doesn't support it just like in this answer : http://stackoverflow.com/questions/7767202/template-specialization-with-variadic-templates?rq=1 ? – Louen Jul 12 '16 at 22:20
  • Which compiler do you use? Clang and MSVC does compile your code and `value` holds 42. – Dean Seo Jul 13 '16 at 00:31

3 Answers3

7

You're not allowed to write a template that is only valid as long as it isn't instantiated. That runs afoul of the following rule in the standard:

If no valid specialization can be generated for a template, and that template is not instantiated, the template is ill-formed, no diagnostic required.

On the other hand, it would be fine if you had something in the body such as

static_assert(sizeof(TYPE) != sizeof(int));

In such a case, the template is valid, and your code will compile since the explicit specialization will in fact be used instead of the primary template. See http://coliru.stacked-crooked.com/a/238b979fd10c62c0

Brian Bi
  • 111,498
  • 10
  • 176
  • 312
3

As state, false is non template dependent, so the static_assert should fire.

You may use = delete in your case:

template <class TYPE, class... ARGS> TYPE Foo(ARGS... args) = delete;

template <> int Foo(float) {return 42;}

Demo

Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • Is not enough `template TYPE Foo(ARGS... args);` in this case? – skypjack Jul 12 '16 at 23:29
  • 1
    @skypjack: It would be link error, whereas we may have compile error with `=delete`. – Jarod42 Jul 12 '16 at 23:31
  • Works fine on live demo, however this does not work in Visual Studio 2015 Update 2. I get `error C2280: attempting to reference a deleted function`. – Erunehtar Jul 15 '16 at 19:51
  • Old versions of gcc/clang has also this bug, see [specialized-template-function-with-deleted-general-case-fails-to-compile-with](http://stackoverflow.com/questions/33256589/specialized-template-function-with-deleted-general-case-fails-to-compile-with) – Jarod42 Jul 15 '16 at 20:02
-2

Your static assert does not depend on the template so it will always fire. Use something like

template <class TYPE, class... ARGS> TYPE Foo(ARGS... args) { 
    static_assert(sizeof(TYPE) != sizeof(TYPE));
}
Daniel
  • 30,896
  • 18
  • 85
  • 139
  • This is equally bad even if a compiler doesn't currently diagnose it. – T.C. Jul 12 '16 at 23:01
  • @T.C.: It does correctly diagnose it - the correct diagnosis for a failed `static_assert` is an error... As the standard states, the stage of the compilation which `static_assert` fails is in the template definition for non dependent expressions, and instantiation for dependent expressions. So if you would like a `static_assert` to fire only upon instantiation, make it dependent, even if the condition itself is not effected by the template arguments. – Daniel Jul 13 '16 at 18:51
  • As no valid specialization of this template can be generated, a compiler is allowed to diagnose this at definition time. The quote is in Brian's answer. – T.C. Jul 13 '16 at 18:54