Suppose we have the following code:
template<typename T>
class C
{};
template <typename T, template <typename> class Container>
void dummyMe(Container<T>&&)
{};
int main(int argc, char* argv[])
{
C<int> c;
dummyMe(c);
return 0;
}
Which doesn't compile due to the first dummyMe argument being an rvalue-reference. Could someone explain me in Standardese why the template template parameters are not getting along with the forwarding references and why is it so in plain English.
P.S. I've stumbled on this and that questions but I do not see any real proofs in the answers.
An answer from the link above and the answer to this question assert that Container<T> can't be counted as a template parameter. And I see no reason why it is so. Let's make the example even simpler:
template <template <typename=int> class Container>
void dummyMe(Container<>&&)
{};
Now we have an example almost identical to the following:
template <typename Container>
void dummyMe(Container&&)
{};
But which is treated in a completely different fashion. Why? Why is Container<>&& can't be considered as the same thing to template <typename=int> class Container as Container&& to typename Container?
The term "forwarding reference" is described at [temp.deduct.call/3](from C++17 draft n4659):
A forwarding reference is an rvalue reference to a cv-unqualified
template parameter that does not represent a template parameter of a
class template (during class template argument deduction).
In your example Container<T> is not a template parameter, it is a type you comprised from the template parameters T and Container. In order for the reference to be truly forwarding, you can use T&& only. While Conatiner is a template parameter, you can't have a reference to a template (the above paragraphs even mentions it explicitly). The type Container<T> is not the same as the template Container. It's an instantiated class.1
While you can use SFINAE to obtain a forwarding reference that can be bound only to the container type, I personally feel you're better off just overloading the function.
template <typename T, template <typename> class Container>
void dummyMe(Container<T>&&)
{}
template <typename T, template <typename> class Container>
void dummyMe(Container<T>&)
{}
1[temp.spec/2] - A class instantiated from a class template is called an instantiated class
An answer from the link above and the answer to this question assert that Container<T> can't be counted as a template parameter
What is or is not a template parameter is not subject to much interpretation. It is clearly defined in [temp.param]:
template-parameter:
type-parameter
parameter-declaration
type-parameter:
type-parameter-key ...(opt) identier (opt)
type-parameter-key identier(opt) = type-id
template < template-parameter-list > type-parameter-key ...(opt) identier(opt)
template < template-parameter-list > type-parameter-key identier(opt) = id-expression
type-parameter-key:
class
typename
It is clear from these production rules that dummyMe has exactly two template parameters: typename T and template <typename> class Container. Identifiers that name each of these parameters are T and Container. T names the first parameter and Container names the second one. Container<T> is not an identifier and names neither of the two.
Related
I've been trying more about multi threaded programming in c++, and i was having difficulty understanding std::promise so i began searching for answers on this website, and low and behold, there is somebody with the same question as me. But reading the answer made me even more confused
this is the code in the answer that presumably is a similar implementation of std::packaged_task
template <typename> class my_task;
template <typename R, typename ...Args>
class my_task<R(Args...)>
{
std::function<R(Args...)> fn;
std::promise<R> pr; // the promise of the result
public:
template <typename ...Ts>
explicit my_task(Ts &&... ts) : fn(std::forward<Ts>(ts)...) { }
template <typename ...Ts>
void operator()(Ts &&... ts)
{
pr.set_value(fn(std::forward<Ts>(ts)...)); // fulfill the promise
}
std::future<R> get_future() { return pr.get_future(); }
// disable copy, default move
};
in this code,
1- what does this syntax mean template <typename R, typename ...Args> class my_task<R(Args...)>, more specifically, what is the purpose of <R(Args...)> ?
2- why is there a foroward decleration for the class?
thanks
There was some brief discussion in the comments how 1 and 2 should be two separate questions, but I believe that they both are just two sides to the same exact question, for the following reasons:
template <typename> class my_task;
template <typename R, typename ...Args>
class my_task<R(Args...)>; ....
The first statement declares a template that takes a typename as its sole template parameter. The second statement declares a specialization for that template class.
In this context:
R(Args...)
Will specialize for any typename that matches a function. This template specialization will match any template instantiation that passes a function signature for a typename. Barring any problems within the template itself, this template specialization will be used for:
my_task<int (const char *)>
or, a function that takes a const char * parameter and returns an int. The template specialization will also match:
my_task<Tptr *(Tptr **, int)>
or, a function that takes two parameters, Tptr ** and an int, and returns a Tptr * (here, Tptr is some other class).
The template specialization will NOT match:
my_task<int>
Or
my_task<char *>
Because they are not function signatures. If you try to instantiate this template using a non-function typename you're going to get a compilation error. Why?
Well, that's because the template is not defined:
template<typename> class my_task;
Don't think of this as just a forward declaration. it's a forward declaration of a template that takes a template parameter, and the template will not be defined anywhere. Rather, the template declaration allows for a subsequent template specialization declaration, that will match only specific types passed as a template parameter.
This is a common programming technique for restricting the kinds of typenames or classes that can be used with a particular template. Instead of allowing a template to be used with just any typename or class, the template can only be used with some subset. In this case, a function typename, or signature.
It also makes it easier for the template itself to explicitly reference -- in this case -- to the template parameter's return type, and the parameter types. If the template has just a bland, single typename as a template parameter, it can't easily access the function's return type, or the function parameter's types.
1: What does this syntax mean template <typename R, typename ...Args> class my_task<R(Args...)>
This is a specialization of the class template my_task. The <R(Args...)> after the name means it is specialized for that type, and that type is a function. R(Args...) is the type of a function taking Args parameters and returning R. So, my_task<void()> mt; for example would make Args be an empty parameter pack, and R would be void.
2: Why is there a forward declaration for the class?
The class is declared, but unlike an ordinary forward declaration, the un-specialized version isn't defined. This class is only intended to work when the type is a function, so if someone tries to use something that isn't a function (like my_task<int>), it will give an error about the type being undefined.
my_task<void*(int, int)> mt1; //R = void*, Args = int, int
my_task<int> mt2; //error: use of undefined class
Suppose the following declaration:
template <typename T> struct MyTemplate;
The following definition of the partial specialization seems to use the same letter T to refer to different types.
template <typename T> struct MyTemplate<T*> {};
For example, let's take a concrete instantiation:
MyTemplate<int *> c;
Now, consider again the above definition of the partial specialization:
template <typename T> struct MyTemplate<T*> {};
In the first part of this line (i.e. template <typename T>), T is int *. In the second part of the line (i.e. MyTemplate<T*>), T is int!
So, how is the definition of the partial specialization read?
Read it like this:
The primary template says "MyTemplate is a class template with one type parameter":
template <typename> struct MyTemplate;
The partial specialization says, "whenever there exists a type T"...
template <typename T>
... such that a specialization of MyTemplate is requested for the type T *"...
struct MyTemplate<T *>
... then use this alternative definition of the template.
You could also define explicit specializations. For example, could say "whenever the specialization is requested for type X, use this alternative definition:
template <> struct MyTemplate<X> { /* ... */ };
Note that explicit specializations of class templates define types, wheras partial specializations define templates.
To see it another way: A partial class template specialization deduces, or pattern-matches, the structure of the class template arguments:
template <typename T> struct MyTemplate<T *>
// ^^^^^^^^^^^^ ^^^^^
// This is a new template Argument passed to the original class
// template parameter
The parameter names of this new template are matched structurally against the argument of the original class template's parameters.
Examples:
MyTemplate<void>: The type parameter of the class template is void, and the primary template is used for this specialization.
MyTemplate<int *>: The type parameter is int *. There exists a type T, namely T = int, such that the requested type parameter is T *, and so the definition of the partial specialization of the template is used for this specialization.
MyTemplate<X>: The parameter type is X, and an explicit specialization has been defined for that parameter type, which is therefore used.
The correct reading of the specialisation is as follows:
template <typename T> // a *type pattern* with a *free variable* `T` follows
struct MyTemplate<T*> // `T*` is the pattern
When the template is instantiated by MyTemplate<int*>, the argument is matched against the pattern, not the type variable list. Values of the type variables are then deduced from the match.
To see this more directly, consider a template with two arguments.
template <typename T1, typename T2>
struct A;
and its specialisation
template <typename T1, typename T2>
struct A<T1*, T2*>;
Now you can write the latter as
template <typename T2, typename T1>
struct A<T1*, T2*>;
(the variable list order is reversed) and this is equivalent to the previous one. Indeed, order in the list is irrelevant. When you invoke A<int*, double*> it is deduced that T1=int, T2=double, regardless of the order of T1 and T2 in the template head.
Further, you can do this
template <typename T>
struct A<T*, T*>;
and use it in A<int*, int*>. It is now plainly clear that the type variable list has no direct correspondence with the actual template parameter list.
Note: the terms "pattern", "type variable", "type pattern matching" are not standard C++ terms. They are pretty much standard almost everywhere else though.
You have this line:
MyTemplate<int *> c;
Your confusion seems to come from assuming that the int * in < > somehow corresponds to the T in template <typename T>. It does not. In a partial specialisation (actually in every template declaration), the template parameter names are simply "free variable" (or perhaps "placeholder") names. The template arguments (int * in your case) don't directly correspond to these, they correspond to what is (or would be) in the < > following the template name.
This means that the <int *> part of the instantiation maps to the <T*> part of the partial specialisation. T is just a name introduced by the template <typename T> prefix. In the entire process, the T is int.
There is no contradiction. T should be read as T, T* is T*.
template <typename T> struct MyTemplate<T*> {};
"In the first part of this line (i.e. template <typename T>), T is int *."
No - in template <typename T> T is int, in struct MyTemplate<T*> {}; T is also int.
"Note that when a partial specialization is used, a template parameter is deduced from the specialization pattern; the template parameter is not simply the actual template argument. In particular, for Vector<Shape*>, T is Shape and not Shape*." (Stroustrup C++, 4th ed, 25.3, p. 732.)
This is from the C++ Standard Library xutility header that ships with VS2012.
template<class _Elem1,
class _Elem2>
struct _Ptr_cat_helper
{ // determines pointer category, nonscalar by default
typedef _Nonscalar_ptr_iterator_tag type;
};
template<class _Elem>
struct _Ptr_cat_helper<_Elem, _Elem>
{ // determines pointer category, common type
typedef typename _If<is_scalar<_Elem>::value,
_Scalar_ptr_iterator_tag,
_Nonscalar_ptr_iterator_tag>::type type;
};
Specifically what is the nature of the second _Ptr_cat_helper declaration? The angle brackets after the declarator _Ptr_cat_helper make it look like a specialization. But instead of specifying full or partial types by which to specialize the template it instead just repeats the template argument multiple times.
I don't think I've seen that before. What is it?
UPDATE
We are all clear that the specialization applies to an instantiation of the template where both template arguments are of the same type, but I'm not clear on whether this constitutes a full or a partial specialization, or why.
I thought a specialization was a full specialization when all the template arguments are either explicitly supplied or are supplied by default arguments, and are used exactly as supplied to instantiate the template, and that conversely a specialization was partial either, if not all the template parameters were required due to the specialization supplying one or more (but not all) of them, and/or if the template arguments were used in a form that was modified by the specialization pattern. E.g.
A specialization that is partial because the specialization is supplying at least one, but not all, of the template arguments.
template<typename T, typename U>
class G { public: T Foo(T a, U b){ return a + b; }};
template<typename T>
class G<T, bool> { public: T Foo(T a, bool b){ return b ? ++a : a; }};
A specialization that is partial because the specialization is causing the supplied template argument to be used only partially.
template<typename T>
class F { public: T Foo(T a){ return ++a; }};
template<typename T>
class F<T*> { public: T Foo(T* a){ return ++*a; }};
In this second example if the template were instantiated using A<char*> then T within the template would actually be of type char, i.e. the template argument as supplied is used only partially due to the application of the specialization pattern.
If that is correct then wouldn't that make the template in the original question a full specialization rather than a partial specialization, and if that is not so then where is my misunderstanding?
It is a partial class template specialization for the case when the same type is passed for both parameters.
Maybe this will be easier to read:
template<typename T, typename U>
struct is_same : std::false_type {};
template<typename T>
struct is_same<T,T> : std::true_type {};
EDIT:
When in doubt whether a specialization is an explicit (full) specialization or a partial specialization, you can refer to the standard which is pretty clear on this matter:
n3337, 14.7.3./1
An explicit specialization of any of the following:
[...]
can be declared by a declaration introduced by template<>; that is:
explicit-specialization:
template < > declaration
and n3337, 14.5.5/1
A primary class template declaration is one in which the class
template name is an identifier. A template declaration in which the
class template name is a simple-template-id is a partial
specialization of the class template named in the simple-template-id. [...]
Where simple-template-id is defined in the grammar like this:
simple-template-id:
template-name < template-argument-list opt >
template-name
identifier
So, wherever there's template<>, it's a full specialization, anything else is a partial specialization.
You can also think about it this way: Full template specialization specializes for exactly one possible instantiation of the primary template. Anything else is a partial specialization. Example in your question is a partial specialization because while it limits the arguments to be of the same type, it still allows for indifinitely many distinct arguments the template can be instantiated with.
A specialization like this, for example
template<>
vector<bool> { /* ... */ };
is a full specialization because it kicks in when the type is bool and only bool.
Hope that helps.
And just a note I feel it's worth mentioning. I guess you already know - function templates can't be partialy specialized. While this
template<typename T>
void foo(T);
template<typename T>
void foo(T*);
might looks like a partial specialization of foo for pointers on the first glance, it is not - it's an overload.
You mention specifying "full or partial types" when performing specialization of a template, which suggests that you are aware of such language feature as partial specialization of class templates.
Partial specialization has rather extensive functionality. It is not limited to simply specifying concrete arguments for some of the template parameters. It also allows defining a dedicated version of template for a certain groups of argument types, based on their cv-qualifications or levels of indirection, as in the following example
template <typename A, typename B> struct S {};
// Main template
template <typename A, typename B> struct S<A *, B *> {};
// Specialization for two pointer types
template <typename A, typename B> struct S<const A, volatile B> {};
// Specialization for const-qualified type `A` and volatile-qualified type `B`
And it also covers specializations based on whether some template arguments are identical or different
template <typename A> struct S<A, A> {};
// Specialization for two identical arguments
template <typename A> struct S<A, A *> {};
// Specialization for when the second type is a pointer to the first one
As another, rather curios example, partial specialization of a multi-argument template can be used to fully override the main template
template <typename A, typename B> struct S<B, A> {};
// Specialization for all arguments
Now, returning to your code sample, partial specialization for two identical arguments is exactly what is used in the code you posted.
I'm working with VS 2008 (sorry, can't update). I need template specialization for my list class. The argument I want to specialize is a member function pointer.
In short, how can I make the following code work (I can' use variadic templates):
// two or three args
template <typename T1, typename T2, void (T1::* FUNC)(const T2&) = 0> struct list;
// specialized code for 2 args.
template <typename T1, typename T2> struct list<T1, T2> { };
The error message is:
C2754: 'specialization' : a partial specialization cannot have a dependent non-type template parameter
Maybe there is no solution for my problem. But that also an answer.
Thanks for your help in advance.
If I do understand correctly what you are trying to achieve, it cannot be done. Let's consider an even simpler case of illegal specialization:
template <typename T1, typename T2, void (T1::* FUNC)(const T2&)> struct list;
template <typename T1, typename T2> struct list<T1, T2, 0> { };
Here you always have to supply three arguments to instantiate your template, and you try to specialize the primary template for the case where the last argument is a null pointer.
Per § 14.5.5/8 of the C++ Standard:
"The type of a template parameter corresponding to a specialized non-type argument shall not be dependent on a parameter of the specialization. [ Example:
template <class T, T t> struct C {};
template <class T> struct C<T, 1>; // error
template< int X, int (*array_ptr)[X] > class A {};
int array[5];
template< int X > class A<X,&array> { }; // error
—end example ]"
You cannot specialize a non-type argument whose type is dependent on other types in the template parameter list. Thus, the above specialization is illegal.
Your original design is just a particular case of this specialization, where the last (non-type) parameter has a default argument value, which you omit in the specialization (omitting it is legitimate per se). The reason why this is illegal is not related with the presence of a default argument, but rather with the fact that you are trying to specialize a non-type argument that has a dependent type.
For templates I have seen both declarations:
template < typename T >
template < class T >
What's the difference?
And what exactly do those keywords mean in the following example (taken from the German Wikipedia article about templates)?
template < template < typename, typename > class Container, typename Type >
class Example
{
Container< Type, std::allocator < Type > > baz;
};
typename and class are interchangeable in the basic case of specifying a template:
template<class T>
class Foo
{
};
and
template<typename T>
class Foo
{
};
are equivalent.
Having said that, there are specific cases where there is a difference between typename and class.
The first one is in the case of dependent types. typename is used to declare when you are referencing a nested type that depends on another template parameter, such as the typedef in this example:
template<typename param_t>
class Foo
{
typedef typename param_t::baz sub_t;
};
The second one you actually show in your question, though you might not realize it:
template < template < typename, typename > class Container, typename Type >
When specifying a template template, the class keyword MUST be used as above -- it is not interchangeable with typename in this case (note: since C++17 both keywords are allowed in this case).
You also must use class when explicitly instantiating a template:
template class Foo<int>;
I'm sure that there are other cases that I've missed, but the bottom line is: these two keywords are not equivalent, and these are some common cases where you need to use one or the other.
For naming template parameters, typename and class are equivalent. §14.1.2:
There is no semantic difference
between class and typename in a
template-parameter.
typename however is possible in another context when using templates - to hint at the compiler that you are referring to a dependent type. §14.6.2:
A name used in a template declaration
or definition and that is dependent on
a template-parameter is assumed not to
name a type unless the applicable name
lookup finds a type name or the name
is qualified by the keyword typename.
Example:
typename some_template<T>::some_type
Without typename the compiler can't tell in general whether you are referring to a type or not.
While there is no technical difference, I have seen the two used to denote slightly different things.
For a template that should accept any type as T, including built-ins (such as an array )
template<typename T>
class Foo { ... }
For a template that will only work where T is a real class.
template<class T>
class Foo { ... }
But keep in mind that this is purely a style thing some people use. Not mandated by the standard or enforced by compilers
No difference
Template type parameter Container is itself a template with two type parameters.
There is no difference between using <typename T> OR <class T>; i.e. it is a convention used by C++ programmers. I myself prefer <typename T> as it more clearly describes its use; i.e. defining a template with a specific type.
Note: There is one exception where you do have to use class (and not typename) when declaring a template template parameter:
template <template <typename> class T> class C { }; // valid!
template <template <typename> typename T> class C { }; // invalid!
In most cases, you will not be defining a nested template definition, so either definition will work -- just be consistent in your use.
This piece of snippet is from c++ primer book. Although I am sure this is wrong.
Each type parameter must be preceded by the keyword class or typename:
// error: must precede U with either typename or class
template <typename T, U> T calc(const T&, const U&);
These keywords have the same meaning and can be used interchangeably inside a template parameter list. A template parameter list can use both keywords:
// ok: no distinction between typename and class in a template parameter list
template <typename T, class U> calc (const T&, const U&);
It may seem more intuitive to use the keyword typename rather than class to designate a template type parameter. After all, we can use built-in (nonclass) types as a template type argument. Moreover, typename more clearly indicates that the name that follows is a type name. However, typename was added to C++ after templates were already in widespread use; some programmers continue to use class exclusively