1

Local type as template argument is forbidden in C++03:

template<typename T>
struct Foo { };

void Make()
{
  struct Unknown {};
  Foo<Unknown> foo; // Bad
}

Is there any directives in Standard about checking this rule in case of template is not instantiated?
Is it possible to be sure, that this rule is checked only after template instantiation attempt (no instantiation => compilation success)?

template<typename T>
struct Foo { };

template<typename T>
void Do(T&) { }

template<typename T>
void Do(T*) // usage with pointer is forbidden by-design
{
  struct Unknown {};
  Foo<Unknown>::UnknownMethod();
}

int main()
{
  std::string s;
  Do(s);
}
DmitriyH
  • 420
  • 4
  • 15
  • May be [`std::static_assert()`](http://en.cppreference.com/w/cpp/language/static_assert) could help to do so. – πάντα ῥεῖ Jun 19 '14 at 09:39
  • 1
    It's not present in C++ 2003 – DmitriyH Jun 19 '14 at 09:41
  • Here's some code, how to implement such yourself with older c++ versions: https://github.com/makulik/StaticInterfaces – πάντα ῥεῖ Jun 19 '14 at 09:43
  • @πάνταῥεῖ How could `static_assert` help here? – Constructor Jun 19 '14 at 09:48
  • @Constructor I thought of just putting it in the function body, that it would trigger a soon the function specialization is instantiated. – πάντα ῥεῖ Jun 19 '14 at 09:51
  • `Is there any directives about checking this rule` I don't know what you mean by this. Please clarify. – Lightness Races in Orbit Jun 19 '14 at 09:52
  • @πάνταῥεῖ As Jan Hudec explains in his answer "the rule does not say that instantiating template with local type as parameter in an error, it says using local type as template parameter is an error". `static_assert` can't help here at all. – Constructor Jun 19 '14 at 10:09
  • @Constructor I more referred to the _'If you need to fail compilation when some combination ...'_ part. – πάντα ῥεῖ Jun 19 '14 at 10:12
  • 2
    @Constructor: As I also explain in my answer, `static_assert` _can_ help here. Because this is typical question of the form "How do I use X to do Y" where the answer is inevitably "use Z instead". Fortunately "Y" is mentioned, so we can say that static assert is the sought-for "Z". – Jan Hudec Jun 19 '14 at 10:12
  • @JanHudec Ah, I didn't notice his comment "usage with pointer is forbidden by-design". Then you and πάντα ῥεῖ are right, `static_assert` is appropriate here for Z part. I mean that it is not suitable for original X-Y. – Constructor Jun 19 '14 at 10:20
  • @πάνταῥεῖ I'm sorry, I didn't noticed that comment. Then you are right, of course. – Constructor Jun 19 '14 at 10:20
  • @πάντα ῥεῖ: `static_assert` is not in the `std` namespace, it is a bit equivalent to `sizeof`, `alignof`, or `decltype` in that regard. – Matthieu M. Jun 19 '14 at 12:02

1 Answers1

2

There is no such directive in C++03, because

  1. There are no directives in C++03 and
  2. the rule does not say that instantiating template with local type as parameter in an error, it says using local type as template parameter is an error.

It is not supposed to be success if the template is not instantiated.

On the other hand, some compilers permit local types as template parameters (e.g. Visual C++; no, it does not follow standard, but that's life), so you can't use that to force compilation failure anyway.

If you need to fail compilation when some combination is attempted, use the standard static assert. You can use the Boost.Static Assert implementation, the implementation linked by πάντα ῥεῖ in comments or the simple implementation in this other question/answer1

template<typename T>
struct Foo { };

template<typename T>
void Do(T&) { }

template<typename T>
void Do(T*) // usage with pointer is forbidden by-design
{
    BOOST_STATIC_ASSERT(false);
}

1I am not sure whether it's correct though; I think that implementation may fail even if not instantiated unless the argument is argument-dependent in the enclosing template.

Community
  • 1
  • 1
Jan Hudec
  • 73,652
  • 13
  • 125
  • 172
  • There's also support in the [Loki library](http://loki-lib.sourceforge.net/), which is a bit more lightweight than boost IMHO. – πάντα ῥεῖ Jun 19 '14 at 10:14
  • @πάνταῥεῖ: I can't find any documentation for it there though. – Jan Hudec Jun 19 '14 at 10:18
  • Yeah Loki's documentation is poor (you should best have access to Alexandrescu's book). – πάντα ῥεῖ Jun 19 '14 at 10:23
  • Yes, it is well described in his *Modern C++ Design* book. His implementation of a static assert is described at the beginning of the second chapter as I remember. – Constructor Jun 19 '14 at 10:28
  • Now I see that Z part is not so obvious. Static assert is still not necessary here. To disable `Do(T*)` overload one should simply not to implement it: `template void Do(T*);`. – Constructor Jun 19 '14 at 10:36
  • @Constructor: In C++11 this is the obvious choice (with `= delete`), however in C++03 this means a link-time error (or even, load-time error) instead of a compile-time error... and it might be non-trivial to understand where the method was called. – Matthieu M. Jun 19 '14 at 12:00