One of my classes declares a templated function:
template<class A, class B>
A do_something(const std::vector<B> &data)
which I'd like to partially specialize on typename A. B is a family of types that implement a pretty minimal interface, and we use a lot of them, so I'd like my specialization to be generic on B. I suspect this is doubly vexing as typename A is used only as the return type.
From the internet, I've gleaned that I can't partially specialize a function, so I've created a class as follows:
template<class A, class B>
class do_something_implementation {
public:
do_something_implementation(const std::vector<B> &data_) {
data = data_;
}
int do_something_implementation<int, B>::operator()() {
/* Complicated algorithm goes here... */
}
double do_something_implementation<double, B>::operator()() {
/* Different complicated algorithm goes here... */
}
private:
std::vector<B> data;
}
When I try to compile that (using Visual Studio 2008), the compiler crashes (!) and I get the following error:
fatal error C1001: An internal error has occurred in the compiler.
I assume this is my problem and not the compiler's. Is there a better way to express the partial specialization I'm aiming for?
Usually, it goes like this:
template <typename A, typename B>
struct DoSomethingHelper
{
static A doIt(const std::vector<B> &data);
};
template <typename B>
struct DoSomethingHelper<double, B>
{
static double doIt(const std::vector<B> &data) { ... }
};
template <typename B>
struct DoSomethingHelper<int, B>
{
static int doIt(const std::vector<B> &data) { ... }
};
template<class A, class B>
A do_something(const std::vector<B> &data)
{ return DoSomethingHelper<A, B>::doIt(data); }
Now that you've seen the classic forward to static method, there is actually another way when the type for which to specialize is "complete".
You may not be able to partially specialize a function, but you can perfectly overload it.
template <typename A, typename B>
A do(std::vector<B> const& data) { return this->doImpl(data, (A*)0); }
template <typename A, typename B>
A doImpl(std::vector<B> const& B, A*) { // generic implementation }
template <typename B>
int doImpl(std::vector<B> const& B, int*) { // int implementation }
template <typename B>
double doImpl(std::vector<B> const& B, double*) { // double implementation }
The trick is to pass an "unused" argument to doImpl for the sole purpose of actually selecting the right implementation (thanks to overload resolution).
Here I simply chose to pass (A*)0, because this does not involve A's constructor (in case it's non trivial).
This dispatch idiom is what is used in the STL to implement some algorithm with better efficiency for some iterator categories (for example, std::distance is O(1) for random iterators).
I find it much more lightweight that using a helper class with static methods and partial specializations... but maybe that's just me :)
People typically just forward to a static implementation.
template<class A, class B> class X;
template<class A, class B> friend class X;
template<class A, class B> class X {
public:
static A do_something(class_type* not_this, const std::vector<B>& data) {
//...
}
};
// partially specialize
template<class A, class B>
A do_something(const std::vector<B> &data) {
return X<A, B>::do_something(this, data);
};
Not a solution to your problem (there are a couple already there), but some of the things that are wrong in your code:
You are missing a struct or class keyword in the template class declaration:
template <typename A, typename B> struct do_something_implementation {
// ^^^^^^
Inside the class definition, member functions must not use a qualified name, regardless of whether the class is a template or not:
class A {
void A::foo() {} // Error, should be: void foo() {}
};
Member template specializations cannot appear inside the class definition, but at the namespace level:
class B {
template <typename T> void foo( T );
};
template <> void B::foo<int>( int ) {}
template <> void B::foo<double>( double ) {}
Plus on your case, the member function is not a template, but rather a non-templated member function (the template is the containing class, not the function itself). What your code is effectively trying to do is defining other class' member functions inside the general template, kind of trying to do.
Overall there was enough errors to make parsing the code almost impossible for the compiler to identify what you were trying to do and provide a good error message, but still, it should have provided any error message pointing to the first line that you copied instead of chocking to death.
Related
Note: this seems to be a repost of a problem: C++ - Overload templated class method with a partial specilization of that method
I have boiled down a problem I am having with C++ template specialization down to a simple case.
It consists of a simple 2-parameter template class Thing, where I would like to specialize Thing<A,B>::doSomething() for B=int.
#include <cstdio>
// A 3-parameter template class.
template <class A, class B>
class Thing
{
public:
Thing(A a, B b) : a_(a), b_(b) {}
B doSomething();
private:
A a_;
B b_;
};
// The generic case works as expected.
template <class A, class B>
B Thing<A,B>::doSomething()
{
return b_;
}
// This specialization does not work!
template <class A>
int Thing<A,int>::doSomething()
{
return b_+1;
}
int main() {
// Setup our thing.
Thing<double,int> thing(1.0,2);
// This doesn't compile - but works with the generic case.
printf("Expecting 3, and getting %i\n", thing.doSomething());
// Clean up.
return 0;
}
Unfortunately, g++ exits with the error:
partial_specialization.cpp:30: error: invalid use of incomplete type ‘class Thing<A, int>’
partial_specialization.cpp:8: error: declaration of ‘class Thing<A, int>’
The clang++ compiler is a bit more verbose, but has the same problem:
partial_specialization.cpp:30:19: error: nested name specifier 'Thing<A, int>::' for declaration does not
refer into a class, class template or class template partial specialization
int Thing<A,int>::doSomething()
~~~~~~~~~~~~~~^
partial_specialization.cpp:32:12: error: use of undeclared identifier 'b_'
return b_+1;
^
2 errors generated.
I have read and understood that partial template specializations on functions aren't allowed - but I thought I was partially specializing over classes of Thing in this case.
Any ideas?
What I did: A workaround, as determined from the link provided by the accepted answer:
template< class T >
inline T foo( T const & v ) { return v; }
template<>
inline int foo( int const & v ) { return v+1; }
// The generic case works as expected.
template <class A, class B>
B Thing<A,B>::doSomething()
{
return foo(b_);
}
Partial specialization of a function template, whether it is member function template or stand-alone function template, is not allowed by the Standard:
template<typename T, typename U> void f() {} //okay - primary template
template<typename T> void f<T,int>() {} //error - partial specialization
template<> void f<unsigned char,int>() {} //okay - full specialization
But you can partially specialize the class template itself. You can do something like this:
template <class A>
class Thing<A,int> //partial specialization of the class template
{
//..
int doSomething();
};
template <class A>
int Thing<A,int>::doSomething() { /* do whatever you want to do here */ }
Note that when you partially specialize a class template, then the template parameter-list of member function (in its definition outside the class), must match the template parameter list of the class template partial specialization. That means, for the above partial specialization of the class template, you cannot define this:
template <class A>
int Thing<A,double>::doSomething(); //error
Its not allowed, because the template parameter-list in function definition didn't match the template parameter-list of the class template partial specialization. §14.5.4.3/1 from the Standard (2003) says,
The template parameter list of a member of a class template partial specialization shall match the template parameter list of the class template partial specialization.[...]
For more on this, read my answer here:
C++ - Overload templated class method with a partial specilization of that method
So what is the solution? Would you partially specialize your class along with all the repetitive work?
A simple solution would be work delegation, instead of partially specializing the class template. Write a stand-alone function template and specialize this as:
template <class B>
B doTheActualSomething(B & b) { return b; }
template <>
int doTheActualSomething<int>(int & b) { return b + 1; }
And then call this function template from doSomething() member function as:
template <class A, class B>
B Thing<A,B>::doSomething() { return doTheActualSomething<B>(b_); }
Since in your particular case, doTheActualSomething needs to know the value of only one member, namely b_, the above solution is fine, as you can pass the value to the function as argument whose type is the template type argument B, and specialization for int is possible being it full-specialization.
But imagine if it needs to access multiple members, type of each depends on the template type argument-list, then defining a stand-alone function template wouldn't solve the problem, because now there will be more than one type argument to the function template, and you cannot partially specialize the function for just, say, one type (as its not allowed).
So in this case you can define a class template instead, which defines a static non-template member function doTheActualSomething. Here is how:
template<typename A, typename B>
struct Worker
{
B doTheActualSomething(Thing<A,B> *thing)
{
return thing->b_;
}
};
//partial specialization of the class template itself, for B = int
template<typename A>
struct Worker<A,int>
{
int doTheActualSomething(Thing<A,int> *thing)
{
return thing->b_ + 1;
}
};
Notice that you can use thing pointer to access any member of the class. Of course, if it needs to access private members, then you've to make struct Worker a friend of Thing class template, as:
//forward class template declaration
template<typename T, typename U> struct Worker
template <class A, class B>
class Thing
{
template<typename T, typename U> friend struct Worker; //make it friend
//...
};
Now delegate the work to the friend as:
template <class A, class B>
B Thing<A,B>::doSomething()
{
return Worker<A,B>::doTheActualSomething(this); //delegate work
}
Two points to be noted here:
In this solution, doTheActualSomething is not a member function template. Its not enclosing class which is template. Hence we can partially specialize the class template anytime, to get the desired effect of the partial member function template specialization.
Since we pass this pointer as argument to the function, we can access any member of the class Thing<A,B>, even private members, as Worker<T,U> is also a friend.
Complete online demo : http://www.ideone.com/uEQ4S
Now there is still a chance of improvement. Now all instantiations of Worker class template are friends of all instantiation of Thing class template. So we can restrict this many-to-many friendship as:
template <class A, class B>
class Thing
{
friend struct Worker<A,B>; //make it friend
//...
};
Now only one instantiation of Worker class template is a friend of one instantiation of Thing class template. That is one-to-one friendship. That is, Worker<A,B> is a friend of Thing<A,B>. Worker<A,B> is NOT a friend of Thing<A,C>.
This change requires us to write the code in somewhat different order. See the complete demo, with all the ordering of class and function definitions and all:
http://www.ideone.com/6a1Ih
This is a very often found problem, and there is a surprisingly simple solution. I will show it in an artificial example, because it's more clearer than to use your code, and you will have to understand it to adapt it to your code
template<typename A, typename B>
struct TwoTypes { };
template<typename A, typename B>
struct X {
/* forwards ... */
void f() { fImpl(TwoTypes<A, B>()); }
/* special overload for <A, int> */
template<typename A1>
void fImpl(TwoTypes<A1, int>) {
/* ... */
}
/* generic */
template<typename A1, typename B1>
void fImpl(TwoTypes<A1, B1>) {
/* ... */
}
};
Explicitly specializing functions is never (almost never?) the right way. In my work as a programmer, I've never explicitly specialized a function template. Overloading and partial ordering is superior.
I have a templated C++ class which has a templated member function as well. The template parameters of this member function are dependent on the class's template parameters in a specific way (please see the code below).
I am instantiating (not specializing) this class for two different values of its template parameter. Everything compiles till this point. However, if I invoke the templated member function, the call for only the first instantiated object compiles and not the second one.
It appears as if the compiler is not instantiating the templated member function for the second instantiation of the template class. I am compiling the code below using "g++ filename.cpp" and am getting the following error:
filename.cpp:63: error: no matching function for call to 'Manager<(Base)1u>::init(Combination<(Base)1u, (Dependent2)0u>*)’
This is the line calling b.init(&combination_2)
g++ --version => g++ (Ubuntu/Linaro 4.4.7-1ubuntu2) 4.4.7
uname -a => Linux 3.2.0-25-generic-pae #40-Ubuntu SMP i686 i686 i386 GNU/Linux
enum Base {
AA,
BB,
CC
};
enum Dependent1 {
PP,
QQ,
RR
};
enum Dependent2 {
XX,
YY,
ZZ
};
template<Base B>
struct DependentProperty {
};
template<>
struct DependentProperty<AA> {
typedef Dependent1 Dependent;
};
template<>
struct DependentProperty<BB> {
typedef Dependent2 Dependent;
};
template <Base B, typename DependentProperty<B>::Dependent D>
class Combination {
public:
void reset() {}
int o;
};
template <Base B>
class Manager {
public:
template <typename DependentProperty<B>::Dependent D,
template<Base,
typename DependentProperty<B>::Dependent> class T>
void init(T<B, D>* t);
};
template <Base B>
template <typename DependentProperty<B>::Dependent D,
template<Base,
typename DependentProperty<B>::Dependent> class T>
void Manager<B>::init(T<B, D>* t) {
t->reset();
}
int main(int argc, char** argv) {
Manager<AA> a;
Manager<BB> b;
Combination<AA, PP> combination_1;
Combination<BB, XX> combination_2;
a.init(&combination_1);
b.init(&combination_2);
return 0;
}
It is not feasible to modify the classes corresponding to Base, Dependent or Combination from my example code in our actual project. What I am really wondering is whether my syntax for defining Manager::init() is wrong, or whether there is some known property/feature/constraint of C++ or g++ that wouldn't allow this code?
The code below compiles for me, I have simplified your code a little, though it still does the same thing.
template <Base B>
class Manager {
public:
typedef typename DependentProperty<B>::Dependent D; // if ever you need it
template <typename TCombinaison>
void init(TCombinaison* t)
{
t->reset();
}
};
int main(int argc, char** argv)
{
typedef Combination<AA, PP> CombinaisonA;
typedef Combination<BB, XX> CombinaisonB;
typedef DependentProperty<AA> DependencyPropertyA;
typedef DependentProperty<BB> DependencyPropertyB;
CombinaisonA combination_1;
CombinaisonB combination_2;
Manager<AA> a;
Manager<BB> b;
a.init(&combination_1);
b.init<&combination_2);
return 0;
}
EDIT: A 2nd solution so as to forbid the mixed use of combination in managers, as the OP has noticed in the comments below. Now I'm using std::is_same to check the "concept" contract.
template <Base B, typename DependentProperty<B>::Dependent D>
class Combination {
public:
typedef typename DependentProperty<B>::Dependent DependencyType;
void reset() {}
int o;
};
template <Base B>
class Manager {
public:
typedef typename DependentProperty<B>::Dependent DependencyType;
template <typename TCombinaison>
void init(TCombinaison* t)
{
static_assert(std::is_same<TCombinaison::DependencyType, Manager::DependencyType>);
t->reset();
}
};
If you combine inheritance and go away from constant template parameters, extend the Combination to provide info on its template arguments, you can get the code to compile taking into account that you don't want this to compile:
b.init(&combination_1);
You are trying very hard to specify and fix the type of the Combination for the init member template within your Manager indirectly, even though the init template will deduce it since it is the only parameter of the function, and the type si defined within main anyway.
Would you consider templating the init directly with the Combination?
This way, everything apart from the init() declaration remains the same, and your code compiles as you wanted to initially:
class Base
{
};
class AA
:
public Base
{
};
class BB
:
public Base
{
};
class Dependent1
{
};
class PP
:
public Dependent1
{};
class Dependent2
{};
class XX
:
public Dependent2
{};
template<class Base>
struct DependentProperty {
};
template<>
struct DependentProperty<AA> {
typedef Dependent1 Dependent;
};
template<>
struct DependentProperty<BB> {
typedef Dependent2 Dependent;
};
template <class Base>
class Combination {
public:
typedef Base CombinationBase;
typedef typename DependentProperty<Base>::Dependent CombinationDependent;
void reset()
{
}
int o;
};
template <class Base>
class Manager
{
public:
// Any type C
template<class C>
void init (C* t)
{
// Any type C conforming to the implicit interface holding reset()
t->reset();
// Forcing specific combination
Base b = typename C::CombinationBase();
// Forcing it again
typename DependentProperty<Base>::Dependent d = typename C::CombinationDependent();
}
};
int main(int argc, char** argv) {
Combination<AA> combination_1;
Manager<AA> a;
a.init(&combination_1);
Manager<BB> b;
Combination<BB> combination_2;
b.init(&combination_2);
b.init(&combination_1);
return 0;
}
In this case, you can extend the Combination template to provide access to its template parameters to the client code. Of course the template C in this case becomes a refinement of the Combination concept as soon as you rely on its implementation within the init member function (accessing the stored template argument values, etc).
Your code is correct, except for the function calling part.
a.init<PP, Combination>( &combination_1 );
b.init<XX, Combination> ( &combination_2 );
This compiles and runs peacefully.
The only thing I see is
template <typename DependentProperty<B>::Dependent D,
template<Base, <-- wrong
typename DependentProperty<B>::Dependent <-- wrong
> class T>
void init(T<B, D>* t);
Your class Combination waits values as a template parameter, but you want to give him types
I spent some time to fix it - like that
template <typename DependentProperty<B>::Dependent D,
template<Base BB,
typename DependentProperty<BB>::Dependent DD
> class T>
void init(T<B, D>* t);
and many other variants, but had no success.
Excuse me for arrange it as an answer, but I couldn't type so many code in a comment
I have a scenario in which there is a template class
template<typename X, typename Y>
class Foo
{
typedef Y::NestedType Bar;
int A (Bar thing);
void B();
int C(X that);
// other stuff
};
and then I would like the A() method to have a different behavior when X is a given type (but B and C can stay the same, and the actual code actually has about 10 other methods, a few of which are quite lengthy and subject to frequent tweaking.. so I would rather avoid making a full-class specialization and copy&paste the full class implementation)
I went on and wrote:
template<typename T>
int Foo<MyType, T>::A(Bar thing);
but my compiler (clang 163.7.1) refused to even consider this as a template specialization of any sort.
Is there some syntax error hidden in the way I wrote the code, or is this coding style invalid C++? Unfortunately, even if other compilers do support the idiom, my company is stuck with clang.
Thanks for any help on this.
Use overloading
template<typename X, typename Y>
class Foo
{
// allows to wrap up the arguments
template<typename, typename>
struct Types { };
typedef Y::NestedType Bar;
int A (Bar thing) {
return AImpl(thing, Types<X, Y>());
}
void B();
int C(X that);
// other stuff
private:
template<typename X1, typename Y1>
int AImpl(Bar thing, Types<X1, Y1>) {
/* generic */
}
template<typename Y1>
int AImpl(Bar thing, Types<SpecificType, Y1>) {
/* special */
}
};
You cannot partially specialize a member of a class template. What you wrote would be the definition of a member function A of a partial specialization of the class template itself.
template<>
class A{
//some class data
};
I have seen this kind of code many times.
what is the use of template<> in the above code?
And what are the cases where we need mandate the use of it?
template<> tells the compiler that a template specialization follows, specifically a full specialization. Normally, class A would have to look something like this:
template<class T>
class A{
// general implementation
};
template<>
class A<int>{
// special implementation for ints
};
Now, whenever A<int> is used, the specialized version is used. You can also use it to specialize functions:
template<class T>
void foo(T t){
// general
}
template<>
void foo<int>(int i){
// for ints
}
// doesn't actually need the <int>
// as the specialization can be deduced from the parameter type
template<>
void foo(int i){
// also valid
}
Normally though, you shouldn't specialize functions, as simple overloads are generally considered superior:
void foo(int i){
// better
}
And now, to make it overkill, the following is a partial specialization:
template<class T1, class T2>
class B{
};
template<class T1>
class B<T1, int>{
};
Works the same way as a full specialization, just that the specialized version is used whenever the second template parameter is an int (e.g., B<bool,int>, B<YourType,int>, etc).
template<> introduces a total specialization of a template. Your example by itself isn't actually valid; you need a more detailed scenario before it becomes useful:
template <typename T>
class A
{
// body for the general case
};
template <>
class A<bool>
{
// body that only applies for T = bool
};
int main()
{
// ...
A<int> ai; // uses the first class definition
A<bool> ab; // uses the second class definition
// ...
}
It looks strange because it's a special case of a more powerful feature, which is called "partial specialization."
Doesn't look right. Now, you might have instead written:
template<>
class A<foo> {
// some stuff
};
... which would be a template specialisation for type foo.
I have a question about template specialization in C++, and I am hoping someone here can help. I have a class that has 3 template parameters:
template<class A, class B, class C>
class myClass {
public:
void myFunc();
};
What I want to do is write several versions of myFunc that specialize on, say, type C, but are generic for types A and B. So I do NOT want the fully templated function like this:
template<class A, class B, class C>
void myClass<A, B, C>::myFunc()
{
// function code here
}
and I do NOT want a fully specialized function like this
void myClass<int, int, int>::myFunc()
{
// code goes here
}
Instead, I want to do something that would be similar to
template<class A, class B>
void myClass<A, B, int>::myFunc()
{
// code goes here
}
The idea is that if class type C is int, I would call one version of myFunc(), and if class type C is double, I would call a different version of myFunc. I've tried lots of difference combinations of template specialization syntaxes (too many to list here), and none seems to compile.
Could someone possibly point me in the right direction here? Thanks in advance for your help.
Michael
You can write a function template, and an overload, and delegate the work to it:
template<class A, class B, class C>
class myClass
{
//resolver doesn't need to define anything in it!
template<class> struct resolver {}; //empty, yet powerful!
public:
void myFunc()
{
doFun(resolver<C>());
}
//this is a function template
template<typename X>
void doFun(const resolver<X> & )
{
//this function will get executed when C is other than int
//so write your code here, for the general case
}
//this is an overload, not a specialization of the above function template!
void doFun(const resolver<int> & )
{
//this function will get executed when C = int
//so write your code here, for the special case when C = int
}
};
Note an important point : doFun(const resolve<int>& ) is an overloaded function, its not a specialization of the function template. You cannot specialize member function template without specializing the enclosing class template.
Read these articles:
Template Specialization and Overloading
Why Not Specialize Function Templates?
Dispatching on a resolver type as #Nawaz shows is IMHO the best way. Another option would be to move the real implementation of that function outside of the class, inside its own struct, make it static and partially specialize the struct. Inside the class, call that. Of course, if it accesses private parts of myClass, you need to make it friend:
template<class A, class B, class C>
class myClass;
template<class A, class B, class C>
struct myClassFuncs{
typedef myClass<A,B,C> class_type;
static void myFunc(class_type* self){
// generic for everything ...
}
};
template<class A, class B>
struct myClassFuncs<A,B,int>{
typedef myClass<A,B,int> class_type;
static void myFunc(class_type* self){
// specialized on C == int ...
}
};
// and so on ...
template<class A, class B, class C>
class myClass{
typedef myClassFuncs<A,B,C> func_holder;
friend class func_holder;
public:
void myFunc(){
func_holder::myFunc(this);
}
};
Though that leads to a lot of wrappers in the class and the specialized versions...
Another idea, which can be said to be pretty crazy, is to not have functions in the class but functors. Those get specialized and then called. This is more verbose, but allows a better access to which functions you want to specialize. Though, if they want to access private parts, you now need to make all of them friends. :/
template<class A, class B, class C>
class myClass;
template<class A, class B, class C>
class myClass_myFunc{
typedef myClass<A,B,C> class_type;
class_type* const _self;
public:
myClass_myFunc(class_type* self)
: _self(self)
{}
void operator() const{
// generic logic here
}
};
template<class A, class B>
class myClass_myFunc<A,B,int>{
typedef myClass<A,B,int> class_type;
class_type* const _self;
public:
myClass_myFunc(class_type* self)
: _self(self)
{}
void operator() const{
// specialized logic here
}
};
template<class A, class B, class C>
class myClass{
friend class myClass_myFunc<A,B,C>;
public:
myClass()
: myFunc(this)
{}
const myClass_myFunc<A,B,C> myFunc;
};