I have two template classes like
template <class T>
class MyClass1{};
template <class T>
class MyClass2{};
and I have a template function using them as an argument. The classes are specialized with std::string:
template <template class<std::string> T> myMethod(T<std::string>& arg){}
I'd like to use myMethod(objectOfMyClass1) and myMethod(objectOfMyClass2), but the code doesn't compile. How to specialize a template class for a template function?
First, if your method does not take any arguments, you won't be able to call it as you want.
Second, MyClass1 and MyClass2 are not classes but class templates -- you cannot therefore have objectOfMyClass1 and objectOfMyClass2.
If you your function to behave specially for an argument of any type of the form SomeClassTemplate<std::string>, then what you're after is partial function template specialization, which is not allowed in C++. You will have to use a partially-specialized class instead:
template <class T>
struct MyMethodCall;
template <template <typename> class T>
struct MyMethodCall<T<std::string> > {
static void call(T<std::string> object) {
...
}
};
template <class T>
void myMethod(T & object) {
MyMethodCall<T>::call(object);
}
This is a compilable example
template <class T>
class MyClass1{};
template <class T>
class MyClass2{};
template <template <typename> class T>
void myMethod(T<std::string>& arg){}
int main()
{
MyClass1<std::string> c1;
myMethod(c1);
MyClass1<std::string> c2;
myMethod(c2);
}
Related
It's easy to write template function override with concept, but I don't know how to write template class partial specialization :(
template <typename T>
concept Integral = is_integral_v<T>;
template <typename T>
concept IsNotIntegral = !
is_integral_v<T>;
template <typename T>
class Test
{
};
template <Integral T> // wrong
class Test
{
};
template <typename T> // wrong
requires Integral<T>
class Test
{
};
int main()
{
Test<int> t;
}
This doesn't work either:(
template <Integral T>
class Test
{
};
template <IsNotIntegral T>
class Test
{
};
Both
template <Integral T> // wrong
class Test
{
};
and
template <typename T> // wrong
requires Integral<T>
class Test
{
};
are using the declaration syntax of a primary class template, not a partial specialization. Compare the syntax of an unconstrained partial specialization from before concepts:
// primary class template
template <typename T>
class Test
{
};
// partial specialization of the class template
template <typename T>
class Test<T*>
{
};
The difference is that there isn't just a class name in the partial specialization after the class keyword, but a template-id Test<T*> instead. Without it a partial specialization makes no sense since we wouldn't know what template arguments we are specializing for.
So with constraints the syntax for a partial specialization should be the same:
template <Integral T>
class Test<T>
{
};
or
template <typename T>
requires Integral<T>
class Test<T>
{
};
Related questions:
c++ nested template specialization with template class
template class specialization with template class parameter
Consider the following code:
template <typename T>
struct is_std_vector: std::false_type { };
template<typename ValueType>
struct is_std_vector<std::vector<ValueType>>: std::true_type { };
Why is such template class specialization syntax correct?
The following seems more logical:
template <typename T>
struct is_std_vector: std::false_type { };
template<> //--- because it is is_std_vector specialization
template<typename ValueType>
struct is_std_vector<std::vector<ValueType>>: std::true_type { };
Class template partial specialization syntax closely mirrors function template syntax. Indeed, the rules for ordering class template partial specializations is based on function template partial ordering.
The way you would write a function taking a vector<T> is:
template <class T>
void is_std_vector(vector<T> ) { ... }
So the way you write a specialization on vector<T> is the same:
template <class T>
class is_std_vector<vector<T>> { ... };
Matching the specialization of is_std_vector would try to deduce T in vector<T> from some type argument A, so it makes a lot of sense that they're written the same way.
For full specializations, we use template <> as placeholder signal to make full specializations look similar to partial specializations. I'm not sure what purpose an extra template <> would serve in this particular case.
I have a struct which I use as template parameter to configure some classes:
template <int _DIM, class _TYPE>
struct CONFIG{
static constexpr int DIM = _DIM;
using TYPE = _TYPE;
};
I then need to partially specialize a class. I currently do this the following way:
Lines that will instantiate the template:
template <class CONFIG> instantiate(){
Calculator<CONFIG::DIM, typename CONFIG::NODE> calc;
}
The template to specialize:
template <class TYPE>
struct Calculator<2, TYPE>{
static void fct(TYPE t){
}
};
Would there be a way to directly instantiate and specialize Calculator with template parameter of type CONFIG?
Change your instantiation like so:
template <class Config> instantiate(){
Calculator<Config> calc;
}
Then specialize like this:
template <class T>
struct Calculator<CONFIG<2, T>>{
static void fct(T t){
}
};
It's generally a bad idea to overload names like you did for the template parameter CONFIG and the struct CONFIG. Although they are related to you, the compiler treats them very differently.
I'm not sure if what I'm trying to do is possible. Here's an example:
template <typename T>
class Ref
{
void Decrement();
};
template <typename T>
class Collection {};
// This will error
template <>
template <typename T>
void Ref<Collection<T>>::Decrement() {}
You can't specialize just one function inside a class template; you have to specialize the class template as a whole.
template <typename T>
class Ref
{
void Decrement();
};
template <typename T>
class Collection {};
template <typename T>
class Ref<Collection<T>> {
void Decrement() {}
};
You can specialize a function template inside a class, i.e., this:
class Ref {
template <typename U> void Decrement();
};
or a function template inside a class template...
template <typename T>
class Ref {
template <typename U> void Decrement();
};
However, even then, a partial specialization, which is what you want to do, cannot be done for a function template; function templates can only be fully specialized for individual types, and never partially specialized, whereas class templates can be either partially or fully specialized.
I am a bit confused about the syntax for template parameters...
How do i specalize this template:
template <typename T> class MyTemplate{
public:
void doSomething(T){}
};
for std::vectors, i.e. I would to write something like
template <std::vector<typename T> > class MyTemplate{
public:
void doSomethingElse(std::vector<T>){}
};
to make the class behave differently, depending on whether the template parameter is just any type T or a vector.
Like this:
template <typename T>
class MyTemplate<std::vector<T> > {
...
};