template class specialization : template-id does not match any template declaration - c++

I'm trying to use templates, but couldn't understand what is wrong with below code.
solve.h
#include "nlp.h"
#include "Ipopt_solve.h"
enum algo_type {IPOPT =1, SQP};
template<int ALG>
class solve
{
public:
solve()
{
}
};
template<>
class solve<IPOPT>
{
public:
solve(nlp*);
private:
Ipopt_solve m_ipopt;
};
solve.cpp
template<>
solve<IPOPT>::solve(nlp* problem): m_ipopt(problem)
{
}
Ipopt_solve is a sub-class of an abstract class TNLP. Ipopt_solve is initialized with a reference to nlp class.
from main.cpp
nlp problem(&model);
solve<IPOPT> solution(&problem);
I'm getting the error like shown below.
error: template-id 'solve<>' for 'solve<1>::solve(nlp*)' does not match any template declaration
solve::solve(nlp* problem): m_ipopt(problem)

This declaration in its original form
template<>
solve<IPOPT>::solve(nlp* problem): m_ipopt(problem)
{
}
is formally valid by itself. However, it is not doing what you think it is doing. This declaration declares an explicit specialization for a member of the main template
template<int ALG>
class solve
{
...
It has no relation to your explicit specialization
template<>
class solve<IPOPT>
{
...
The compiler is trying to specialize constructor solve<ALG>::solve(nlp* problem) of the main template. However, the main template has no such constructor. Hence the error message, that tells you exactly that: the compiler does not understand what constructor you are trying to specialize, it cannot find the matching member in the main template.
For example, you can use this syntax to explicitly specialize the default constructor of the main template
template<>
solve<SQP>::solve()
{
// Specialized code for `solve<SQP>`'s default constructor
}
This will compile fine since the main template does indeed have such constructor. (Note that you don't have to explicitly specialize the whole class for that, you can just explicitly specialize the constructor.)
Your intent was, obviously, completely different: to provide definition for the constructor in the class template specialization
template<>
class solve<IPOPT>
{
...
The proper syntax for that should not mention template<>
solve<IPOPT>::solve(nlp* problem): m_ipopt(problem)
{
}

You should remove template<>, i.e.
// template <>
solve<IPOPT>::solve(nlp* problem): m_ipopt(problem)
{
}
template<> is used for template specialization (for a template); but you're just defining a non-template member function (of a class template specialization). (That's why the compiler complains that the template declaration can't be found.)

Related

Is it legal to perform partial in-class specialization of a member template class in derived class

It is continuation of this question. I am specifically interested if the partial specialization of a member class like this:
struct FooParent {
template <class>
struct Bar{ };
};
struct Foo: FooParent {
template <class T>
struct Bar<T*> {};
};
I know this can be done inside a namespace scope:
template <class T>
struct Foo::Bar<T*>{ };
But I'm also specifically interested in in-class partial specialization at the level of derived class.
Both clang and gcc complains when encounter a former:
clang states that there is an explicit template specialization which obviously does not occur:
error: explicit specialization of 'Bar' in class scope
gcc is a little bit less verbose here and says that the specialization of the member template must be performed at a namespace scope which obviously is not a case for not derived class.
error: specialization of 'template struct FooParent::Bar' must appear at namespace scope
Is gcc right here in his error message?
I'm trying to sum up what I said in the comments to the question, as requested by the OP.
I guess [temp.class.spec]/5 is enough to reply to the question.
In particular:
A class template partial specialization may be declared or redeclared in any namespace scope in which the corresponding primary template may be defined [...].
In this case, what actually rule on it is where the primary template can be defined.
In the example, you are trying to declare (and contextually define, but it's first of all a declaration) a partial specialization in a derived class.
The short answer is: you cannot define the primary template in the derived class, so you cannot declare a partial specialization in that class as well.
If it was possible , the following would have been possible too:
struct FooParent {
template <class>
struct Bar;
};
struct Foo: FooParent {
template <class T>
struct FooParent::Bar<T*> {};
};
Or this one if you prefer:
struct Foo: FooParent {
template <class T>
struct Bar<T*> {};
};
Unfortunately (?) they are not allowed and this would suffice to tell you that your attempt to specialize the class template is invalid as well.
Anyway, let's consider it a bit further.
The primary template is part of the member specification of Foo (see here for further details).
Thus, the question - where can I define such a template?, quickly becomes - where can I define any other member of the class?.
Again, the answer is - not in the scope of a derived class.
I'm pretty sure that a language-lawyer would give you more direct and straightforward explanation.
I'm also pretty sure that the same language-lawyer would curse me for having mentioned the wrong sections of the standard.
Anyway, I hope the few examples above can give you a base point from which to start.

Mixing explicit class specialization and class method specialization?

So I've got a class that wants to instantiated for exactly one of two classes. I declare it in the header:
template <class T>
class MyClass {
public:
bool DoSomethingGeneric();
bool DoSomethingTSpecific();
};
Since I don't want to place the method definitions in the header, I instead place them in the implementation file, and perform an explicit specialization. While the DoSomethingGeneric method can be defined generically using a template, the DoSomethingTSpecific requires two separate implementations, one for each of the two possible classes for which I want to instantiate MyClass:
template <class T>
bool MyClass<T>::DoSomethingGeneric() {
// Generic code
}
template <>
bool MyClass<ClassA>::DoSomethingTSpecific() {
// ClassA-specific implementation
}
template <>
bool MyClass<ClassB>::DoSomethingTSpecific() {
// ClassB-specific implementation
}
Now, riddle me this: where do I place the explicit specialization? If I place it after my template definitions (like I usually do with specializations of purely-generic classes), clang says:
explicit specialization of 'MyClass<ClassA>' after instantiation
This message is accompanied by a pointer to the line where DoSomethingTSpecific is defined. This makes sense. My understanding is that the explicit specialization of the DoSomethingTSpecific method counts as an implicit specialization.
Meanwhile, if I place the specializations after all the template definitions, I see:
no function template matches function template specialization 'DoSomethingTSpecific'
This one is kind of a mystery to me.
Any thoughts? How can I have an explicit class-level specialization and explicit method specialization?
From the C++ Standard §14.7.3(5) Explicit specialization (emphasis mine):
Members of an explicitly specialized class template are
defined in the same manner as members of normal classes, and not using the template<> syntax.
Example:
template <> // specialization for classA
class MyClass<ClassA> {
public:
bool DoSomethingTSpecific(); // must be declared here
};
// template<> is not used here
bool MyClass<ClassA>::DoSomethingTSpecific() {
// ClassA-specific implementation
}
Demo:
http://cpp.sh/3tc2g

Specialization of member function template after instantiation error, and order of member functions

The following bit of code fails to compile on gcc 4.5.3
struct Frobnigator
{
template<typename T>
void foo();
template<typename T>
void bar();
};
template<typename T>
void Frobnigator::bar()
{
}
template<typename T>
void Frobnigator::foo()
{
bar<T>();
}
template<> // error
void Frobnigator::foo<bool>()
{
bar<bool>();
}
template<>
void Frobnigator::bar<bool>()
{
}
int main()
{
}
Error message: specialization of ‘void Frobnigator::bar() [with T = bool]’ after instantiation. I finally resolved this problem by having the specialization of Frobnigator::bar<bool>() appear before Frobnigator::foo<bool>(). Clearly the order in which the methods appear matter.
Why then is the following lite version of the above code, in which the the specialization of bar appears after the generic version, valid ?
struct Frobnigator
{
template<typename T>
void foo();
};
template<typename T>
void Frobnigator::bar()
{
}
template<>
void Frobnigator::bar<bool>()
{
}
int main()
{
}
Your first code is not correct by standard.
n3376 14.7.3/6
If a template, a member template or a member of a class template is explicitly specialized then that specialization shall be declared before the first use of that specialization that would cause an implicit instantiation
to take place, in every translation unit in which such a use occurs; no diagnostic is required.
In your case - implicit instantiation of bar function with type bool is required by its usage in foo<bool>, before explicit specialization declaration.
Clearly the order in which the methods appear matter.
Indeed; as is usually the case in C++, you can't use something before it's declared, and this applies to explicit template specialisations as well as most other things.
Using bar<bool> (by calling it from foo<bool>) without a previous declaration of an explicit specialisation causes that specialisation to be instantiated from the generic template, if it hasn't already been. You'll need at least a declaration of the explicit specialisation to prevent that.
Why is this the case, considering that the specialization of bar appears after the generic version in the following lite version of the above code
The second example differs by not instantiating foo<bool> at all. The issue isn't that the specialisation is declared after the generic template (which must be the case), but that it's declared after that specialisation has already been instantiated.

Explicit specialization of non-class, non-function members of a class template

Look at the code:
template <class x> struct Foo
{
int getX(x *p) { return(0); }
enum E12 { a };
};
template <> int Foo<int>::getX(int*)
{
return(-15);
}
template <> enum Foo<int>::E12
{
a, b, c
}
As it was discussed in Cannot overload function, the first specialization is legal and even works in MSVC. While the second specialization for enum does not even want to compile, saying "error C2988: unrecognizable template declaration/definition".
It seems to me that C++ is making relaitively unlogical exception for methods. Enum is just an example. The same thing can be applied to member classes, typedefs, etc.
I will be happy is some body will comment on this.
This is a very obscure new feature of C++11. File a bug report with Microsoft, although it is unlikely it will be given priority as almost nobody is aware this is allowed. The correct syntax would be
template <class x> struct Foo
{
int getX(x *p) { return(0); }
enum E12 { a };
};
template <> int Foo<int>::getX(int*)
{
return(-15);
}
template <> enum Foo<int>::E12
{
a, b, c
};
I've filed a bug with GCC. Can someone test on recent Clang?
In C++03, only classes and functions may be explicitly specialized. From the standard, C++03 14.7.3/1:
An explicit specialization of any of the following:
function template
class template
member function of a class template
static data member of a class template
member class of a class template
member class template of a class or class template
member function template of a class or class template
can be declared by a declaration introduced by template<>
A member enum is not such a case. (Generally speaking, an enum type is always defined only once at its first declaration.)
To obtain a templated enum or typedef, you can wrap it in a class template. In your case, it would be a member class template of Foo. Such a construct is called a metafunction.
C++11 also has alias templates, which are like templated typedefs, but they cannot be explicitly specialized.
The policy of only allowing classes and functions to be specialized, and then allowing such templates to encapsulate other things like enum and typedef, seems more consistent to me than allowing direct specialization of enum. But, perhaps the language is going in your preferred direction.

what does template<> (without any class T in the <>) mean?

I'm reading some source code in stl_construct.h,
In most cases it has sth in the <>
and i see some lines with only "template<> ...".
what's this?
This would mean that what follows is a template specialization.
Guess, I completely misread the Q and answered something that was not being asked.
So here I answer the Q being asked:
It is an Explicit Specialization with an empty template argument list.
When you instantiate a template with a given set of template arguments the compiler generates a new definition based on those template arguments. But there is a facility to override this behavior of definition generation. Instead of compiler generating the definition We can specify the definition the compiler should use for a given set of template arguments. This is called explicit specialization.
The template<> prefix indicates that the following template declaration takes no template parameters.
Explicit specialization can be applied to:
Function or class template
Member function of a class template
Static data member of a class template
Member class of a class template
Member function template of a class template &
Member class template of a class template
It's a template specialization where all template parameters are fully specified, and there happens to be no parameters left in the <>.
For example:
template<class A, class B> // base template
struct Something
{
// do something here
};
template<class A> // specialize for B = int
struct Something<A, int>
{
// do something different here
};
template<> // specialize both parameters
struct Something<double, int>
{
// do something here too
};