I have defined a class Bar inside a member function (constructor) Foo, that I am trying to use as a template parameter.
template<typename Ty>
struct Spam {
template<class U, class D> Spam(U*, D) {}
};
struct Foo {
Foo() {
struct Bar {};
int *ptr = NULL;
Spam<int> pSpam(ptr, Bar());
}
};
My guess is that the usage is invalid as the scope of Bar is local to Foo and cannot have a global visibility which is required for template instantiation. But on a second though, I am instantiating the template in the same scope of Bar, and though the template class/struct is global, there should not be any accessibility issues of the template instance.
I tried across multiple compilers, and each behaves differently. Particularly
clang accepted with warning
warning: template argument uses local type 'Bar' [-Wlocal-type-template-args]
VC++ compiled without warning
GCC 4.3.4 compilation failed
10 : error: no matching function for call to 'Spam::Spam(int*&, Foo::Foo()::Bar)'
3 : note: candidates are: Spam::Spam(const Spam&)
GCC C++14 compiled successfully
What is the expected behaviour according to the standards?
C++2003 standard 14.3.1/2 specify that
A local type, a type with no linkage, an unnamed type or a type compounded from any of these types shall not be used as a template-argument for a template type-parameter.
template <class T> class X { /* ... */ };
void f()
{
struct S { /* ... */ };
X<S> x3; // error: local type used as template-argument
X<S*> x4; // error: pointer to local type used as template-argument
}
But it is allowed in C++11 and higher.
N3797 14.3.1/2
template <class T> class X { };
template <class T> void f(T t) { }
struct { } unnamed_obj;
void f()
{
struct A { };
enum { e1 };
typedef struct { } B;
B b;
X<A> x1; // OK
X<A*> x2; // OK
X<B> x3; // OK
f(e1); // OK
f(unnamed_obj); // OK
f(b); // OK
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With