Reputation: 2453
Is it possible to use a class template as parameter in a template specialization?
I would like to be able to use something like foo<Foo<int>>()
(see #3
in source code) and have unique code for that template instance run. At the moment only ordinary specialization works (see #2
).
A previous similar question would have me believe approach #3
would work, but the code doesn't work under msvc2012 at least.
Is what I'm trying to do possible? If so, how?
Source
// Test struct.
template<class T>
struct Foo
{
T foo;
};
// #1 Ordinary template
template<class T>
T foo()
{
return T();
}
// #2 Template specialization
template<>
int foo<int>()
{
return 42;
}
// #3 Template specialization with template as parameter? Not working.
template<>
template<typename T>
Foo<T> foo<Foo<T>>()
{
return Foo<T>();
}
Upvotes: 1
Views: 111
Reputation: 2453
I rewrote Marco A.'s solution to allow me to keep my original syntax.
Then, I also came up with a second solution which uses "out parameters" instead of "return values". I think this solution is is better as it is simper to maintain and accomplishes the same job.
Solution #1 (Rewritten Marco A's solution with original syntax)
#include <iostream>
using namespace std;
// Test struct
template<class T>
struct Foo
{
T foo;
};
// #1 Ordinary template
template<class T>
struct FooWrapper
{
static T foo()
{
return T();
}
};
// #2 Template specialization
template<>
struct FooWrapper<int>
{
static int foo()
{
return 42;
}
};
// #3 Template specialization with template as parameter
template<class T>
struct FooWrapper<Foo<T>>
{
static Foo<T> foo()
{
return Foo<T>();
}
};
// Hides wrapper implementation
template<class T>
T foo()
{
return FooWrapper<T>::foo();
}
int main()
{
cout << foo<bool>() << endl;
cout << foo<int>() << endl;
cout << foo<Foo<int>>().foo << endl;
return 0;
}
Solution #2 (Simpler, possible better solution using out parameters)
#include <iostream>
using namespace std;
// Test struct
template<class T>
struct Foo
{
T foo;
int bar;
};
// #1 General case
template<class T>
void foo(T& value)
{
value = T();
}
// #2 Special case
void foo(int& value)
{
value = 2;
}
// #3 Special case with class template
template<class T>
void foo(Foo<T>& value)
{
value.bar = 3;
}
// Function templates with hidden specializations
template<class T>
T foo()
{
T value;
foo(value);
return value;
}
int main()
{
cout << foo<bool>() << endl;
cout << foo<int>() << endl;
cout << foo<Foo<int>>().bar << endl;
return 0;
}
Upvotes: 0
Reputation: 43662
Functions can't be partially specialized, you need to wrap it up into a class or struct
#include <iostream>
using namespace std;
// Test struct.
template<class T>
struct Foo
{
T foo;
};
// Struct specialization
template<>
struct Foo<bool>
{
static const int val = 46;
};
// #1 Ordinary template
template<class T>
struct functionWrapper {
static T foo() {
return T();
}
};
// #2 Template specialization
template<>
struct functionWrapper<int> {
static int foo() {
return 42;
}
};
// #3 Template specialization with template as parameter
template<class T>
struct functionWrapper<struct Foo<T>> {
static Foo<T>* foo() {
return new Foo<T>();
}
};
int main() {
cout << functionWrapper<bool>::foo() << endl;
cout << functionWrapper<int>::foo() << endl;
Foo<bool> *obj = functionWrapper<Foo<bool>>::foo();
cout << obj->val;
delete obj; // Always be a good citizen
return 0;
}
Upvotes: 2