Nested template parameters for functions - c++

template <typename T> class foo2 {
};
Sample 1
template <typename T, template <typename> class foo2>
foo2<T> func2(){
}
Sample 2
template <template <typename T> class foo2>
foo2<T> func2(){
}
I have a template class and I would like to write a function that accepts only that class (with any of it's templates of course)
why does sample 1 works and 2 does not?
Edit:
Please provide an explanation of how the matching happens? Clearly the function in sample 1 takes two template parameters without any default values, however in the call in the main only one parameter is provided.
Edit2:
I want another func2 overload for the templated foo2 class, I already have defined in my code.
template <typename T>
T func2(){
}

Template template parameters define a template name in the body of the function. You have to provide the parameter to instantiate them. This means that the T in
template <template <typename T> class foo2> void func2(foo2<T>);
is not visible elsewhere; only the template name foo2 is.
Your first sample,
template <typename T, template <typename> class foo2> void func2(foo2<T>);
works because the T is a top-level template type parameter, which is
visible to the function body, and
deduced from the function argument.
However, this use case is more easily written with a simple template type parameter and direct use of the class foo2:
template <typename T> void func2(foo2<T>);
See, for example, template parameters and template arguments on cppreference for details
Note, the question was edited after I wrote the above, and the type is no longer used as a function argument. The point about type deduction no longer applies, but the rest of the answer stands.

Related

When specializing a class, how can I take a different number of template parameters?

I just asked this question: Can I get the Owning Object of a Member Function Template Parameter? and Yakk - Adam Nevraumont's answer had the code:
template<class T>
struct get_memfun_class;
template<class R, class T, class...Args>
struct get_memfun_class<R(T::*)(Args...)> {
using type=T;
};
These is clearly an initial declaration and then a specialization of struct get_memfun_class. But I find myself uncertain: Can specializations have a different number of template parameters?
For example, is something like this legal?
template<typename T>
void foo(const T&);
template<typename K, typename V>
void foo<pair<K, V>>(const pair<K, V>&);
Are there no requirements that specializations must take the same number of parameters?
You seem to confuse the template parameters of the explicit specialization and the template arguments you use to specialize the template.
template<class T> // one argument
struct get_memfun_class; // get_memfun_class takes one template (type) argument
template<class R, class T, class...Args>
struct get_memfun_class<R(T::*)(Args...)> {
// ^^^^^^^^^^^^^^^^
// one type argument
using type=T;
}; // explicit specialization takes one template argument
Yes, there are three template parameters for the explicit specialization, but that doesn't mean that the explicit specialization takes three arguments. They are there to be deduced. You can form a single type using multiple type parameters, which is what is happening there. Also consider that you can fully specialize a template:
template <>
struct get_memfun_class<void>;
// ^^^^
// one type argument
Here it's the same thing. Yes, the explicit specialization takes no parameters, but that just means that there is none to be deduced and indeed you are explicitly writing a template parameter (void) and so the amount of template arguments of the specialization match those of the primary template.
Your example is invalid because you cannot partially specialize functions.
Are there no requirements that specializations must take the same number of parameters?
There is; and is satisfied in your example.
When you write
template<class T>
struct get_memfun_class;
you say that get_mumfun_class is a template struct with a single template typename argument; and when you write
template<class R, class T, class...Args>
struct get_memfun_class<R(T::*)(Args...)> {
using type=T;
};
you define a specialization that receive a single template typename argument in the form R(T::*)(Args...).
From the single type R(T::*)(Args...), you can deduce more that one template paramenters (R, T and the variadic Args..., in this example) but the type R(T::*)(Args...) (a method of a class that receive a variadic list of arguments) remain one.
For example, is something like this legal?
template<typename T>
void foo(const T&);
template<typename K, typename V>
void foo<pair<K, V>>(const pair<K, V>&);
No, but (as written in comments) the second one isn't a class/struct partial specialization (where std::pair<K, V> remain a single type), that is legal; it's a template function partial specialization that is forbidden.
But you can full specialize a template function; so it's legal (by example)
template<>
void foo<std::pair<long, std::string>(const std::pair<long, std::string>&);
as is legal the full specialization for get_memfun_class (to make another example)
template<>
struct get_memfun_class<std::pair<long, std::string>> {
using type=long long;
};

Function with multiple template specifiers

I do not understand the template defined below, can somebody help me decode it?
template <typename Impl>
template <typename datadec, typename T>
inline datadec<Impl>::codec(const T& value)
{
return codec<datadec>(Master::char_data(value), Master::size(value));
}
First of all, in case this isn't clear, the snippet as given by the OP doesn't compile. In keeping with what I believe is the intention behind it, two minimal modifications are needed to make it compile:
template <typename Impl>
template <typename datadec, typename T>
inline auto ::datadec<Impl>::codec(const T& value)
{
codec<datadec>(Master::char_data(value), Master::size(value));
}
To answer the question, let's go over this line by line:
So, the datadec class template takes the single template argument typename Impl. Hence the first line:
template <typename Impl>
Now, the next two lines:
template <typename datadec, typename T>
inline auto ::datadec<Impl>::codec(const T& value)
constitute a definition for a member function template codec() of this class template datadec (so it's a member function template of a class template). This function template itself takes two template arguments: typename datadec and typename T. Note that the first template argument here is of the same name as the class template itself -- datadec.
Notice: In the OP there was a return value type missing from this function declaration.
Next we see what's inside the member function definition:
{
return codec<datadec>(Master::char_data(value), Master::size(value));
}
there's a call to a different codec() that is explicitly being used with a template argument that gets the datadec template parameter passed from the outside and takes two non-template arguments: Master::char_data(value) and Master::size(value).
Edit: In an attempt to shed light on the "dual role" of the datadec name in this snippet -- as it seems to raise some eyebrows that this argument (taken by the member function template) is of the same name as the class template itself, as noted above: Without being provided more context by the OP, let's imagine, from a design perspective, that the class template datadec represents some data decoder and that codec() returns some codec related data. Then one reasonable explanation for these templated declarations to be as they are is that codec() needs to know what type of data decoder it needs to use for its return value -- as in, you could specialize the two argument version of codec() for different types of datadec.

Multiple template functions inside non-template class

I have a class foo which contain two template functions Add() and Subtract().
struct foo
{
template <typename U>
U* Add();
template <typename U>
U* Subtract();
};
Is it correct to use same template parameter U for both of them? Also do I need to write template <typename U> every time before a template function declaration?
Yes, you can use the same name for template parameters in different functions, the same way you can name arguments the same. Those names in different functions are completely unrelated.
And yes, you have to use keyword template as per C++ grammar.

partial specialization of template class with a template template parameter

template <typename T, template <typename> class Bar>
class Foo
{
Bar<T> bar;
};
I'm trying to make a specialization of this class that would be of type Foo<Bar<Foo>> where Bar is an arbitrary template class with 1 template parameter. Can anyone show me how to do this? Also, I don't want to stick to this particular template class definition. If it can be done by using a different definition of Foo that's fine, too.
EDIT:
What I meant is that I want the specialization to be of type Foo<Foo, Bar<Foo>>

Need help regarding Template class instantiation

Let me present my problem with an example :
template <typename T> class a{
public:
T data;
a():data(T()){}
a(T temp): data(temp) {}
};
So if write in main() like
a(30);
a("String");
So according to the template argument deduction rule , it should be able to generate the first temporary class as a<int>(30) etc
But I the error which says:
missing template arguments before '(' token
so why this happens, this is only true for function template?
Template parameter deduction from arguments only works for functions, never for classes. Until you know the type of the class, i.e. all its template parameters, you don't even know which member functions the class has!
So, you always have to say the template parameters if you want to construct an object directly:
a<int> x(30);
Here's a little thought experiment to expand on the above. Suppose we have
template <typename T> class Foo;
and we are calling Foo::somefunction(x);, where x is some type. You think, well, I declared somefunction() like this:
template <typename T> class Foo
{
static void somefunction(const T & x);
};
so it should be obvious that T is the same type as the type of x. But now imagine I have a specialization:
template <> class Foo<char>
{
static void anotherfunction(double x);
};
The class Foo<char> doesn't even have a function somefunction(), so the expression Foo::somefunction(x) doesn't even get to the stage where I could look up the argument!
The usual way around this is to make a free helper function that constructs your object:
template <typename T> a<T> make_a(const T & x) { return a<T>(x); }
Since this is a function template, its parameters can be deduced:
make_a(30); // type a<int>
make_a("hello"); // type a<char[6]>
The constructor is not a template, its the class which is a template. So when you write a(30), the template argument deduction for the class template cannot be done!
If there exists a constructor template, then the template argument for the templated constructor can be deduced by the compiler. For example here:
template <typename T> class A{
public:
template<typename U>
A(const U &): {} //note : it's a constructor template
};
A<char> obj(30); //U is deduced as int
In the above example, only U can be deduced, you still have to provide T. Its because
U is a template argument for the constructor template. Template argument deduction can be done in this case.
T is a template argument for the class template. Template argument deduction cannot be done here.
You still need to declare a temporary as, for example, a<int>(30).
You cannot infer class template arguments from the arguments to the constructor- unfortunately.
Template type deduction only happens for template functions. You need to specify the parameters for a template class instantiation . You can use a function template to deduce the template parameter and return the appropriate type. In c++0 x you could use auto to hold the instance. Can't easily write example code for you on my phone!