This example code generates expected a class template, got std::pair <_T1, _T2>. I tried using struct Struct <std::pair> {};, but then parameters T and M become undeducible. How to avoid this?
template <template <class...> class>
struct Struct {};
template <class T, class M>
struct Struct <std::pair <T, M>> {};
Depending of what you want
template <template <class...> class>
struct Struct {};
template <>
struct Struct <std::pair>
{
// Specialization
};
or
template <typename> struct Struct {};
template <typename First, typename Second>
struct Struct <std::pair<First, Second>>
{
// Specialization
};
That is not a valid specialization for your template.
The reason why is because std::pair<T, M> is a full specialization of the class template std::pair and therefore a class. Your template expects a class template parameter which is exactly what the compiler is telling you.
Related
I have the following class:
template <typename T, typename U = UDefault>
class A;
How to check whether types such as A<float> or A<float, int> are instances of the above templated class?
I tried modifying How to check if an object is an instance of a template class in C++? into:
template <typename T, typename U>
struct IsA : std::false_type
{};
template <typename T, typename U>
struct IsA<A<T, U>> : std::true_type
{};
but it's giving the following error
20:18: error: wrong number of template arguments (1, should be 2)
16:8: error: provided for 'template<class T, class U> struct IsA'
In function 'int main()':
40:34: error: wrong number of template arguments (1, should be 2)
16:8: error: provided for 'template<class T, class U> struct IsA'
How can this be solved?
Your IsA class should be expected to take one template argument. The type you are testing.
template <typename Type>
struct IsA : std::false_type {};
template <typename T, typename U>
struct IsA< A<T,U> > : std::true_type {};
// ^^^^^^ The specialization of your one template argument.
Or put alternately, since the individual template parameters to A do not matter here:
template <typename ...AParams>
struct IsA< A<AParams...> > : std::true_type {};
// ^^^^^^^^^^^^^ The specialization of your one template argument.
See it work in Compiler Explorer
I'm trying to create an variant struct, i.e. a struct that contains one of so many types. Here is my attempt so far:
template <typename Type, typename... Rest> struct OneOf {
union {
Type value;
OneOf<Rest...> rest;
};
};
template <typename Type> struct OneOf {
Type value;
};
Sadly, this doesn't compile. When I try to instantiate it, I get:
one_of.h:34:33: error: redeclared with 1 template parameter template
struct OneOf {
Is there a way to terminate a self referencing recursion with structs?
You have to first declare the primary template, and then declare any specializations (either full or partial). The primary template determines the number and kind of template arguments. When it comes time to instantiate the template, a full specialization will be used if it matches exactly, or the best-matching partial specialization if any match, otherwise, the primary template will be instantiated.
If you want OneOf to be a template that takes any number of type template arguments (0 or more), then you should declare the primary template accordingly:
template <class... T> struct OneOf;
Then you'll need two specializations: one for the base case of the recursion, which can be taken to be the empty pack:
template <>
struct OneOf<> {};
and one for the recursive case, with at least one template parameter:
template <typename Type, typename... Rest> struct OneOf<Type, Rest...> {
union {
Type value;
OneOf<Rest...> rest;
};
};
Notice that both full and partial specializations require a template argument list after the template name. If you omit this, the compiler will think you are redeclaring the primary template, which causes the error you're seeing.
I assume you are trying to write a specialization.
This is the syntax:
template <typename Type> struct OneOf<Type> {
// ^~~~~~
Type value;
};
What about
template <typename...>
struct OneOf;
template <typename Type, typename... Rest>
struct OneOf<Type, Rest...> {
union {
Type value;
OneOf<Rest...> rest;
};
};
template <>
struct OneOf<> {
};
?
O also
template <typename, typename...>
struct OneOf;
template <typename T0, typename T1, typename ... Ts>
struct OneOf<T0, T1, Ts...> {
union {
T0 value;
OneOf<T1, Rest...> rest;
};
};
template <typename T0>
struct OneOf<T0> {
T0 value;
};
?
I'd like to specialize a class template on the type template parameter of the template template parameter. Is it possible? If yes, what is the syntax?
#include <type_traits>
template <typename T>
struct X {};
// primary template
template<template<class> class C>
struct Z : std::false_type {};
// specialization on the template template parameter
template<>
struct Z<X> : std::true_type {}; // OK
// specialization on the type template parameter of the
// template template parameter
template <template<class> class C>
struct Z<C<int>> {}; // ERROR
Motivation: Let's assume that the template template parameter denotes Collections (e.g. std::vector, std::deque). And I want to specialize Z on std::vector but I am not interested about the type template parameter of std::vector, that's OK. Also I want to specialize on all Collection types, which holds an int.
This question is similar to the following questions, but they are either trying to specialize a function template
How to specialize a template with template-tempate parameters
Specialize a template with a template
or they are trying to specialize not on the template template parameter
Specialization and template template parameters
or there's no template template parameter in the primary template
Templated class specialization where template argument is a template
The following code compiles fine:
#include <type_traits>
template <typename T>
struct X {};
// primary template, no template template parameter
template<typename T>
struct Z : std::false_type {};
// specialization on the template template parameter with arbitrary T
template<typename T>
struct Z<X<T>> : std::true_type {};
// here's where you need the template template parameter
template <template<class> class C>
struct Z<C<int>> : std::true_type {};
int main()
{
static_assert(!Z<Z<double>>::value, "" );
static_assert( Z<Z<int >>::value, "" );
static_assert( Z<X<double>>::value, "" );
// static_assert( Z<X<int >>::value, "" ); // error: ambiguous
// partial specialization
}
In your code you give Z a template template parameter, even though that should be done for the specialization only. That's why your code does not compile.
This cannot work because in your code:
template<template<class> class C>
struct Z : std::false_type {};
template<>
struct Z<X> : std::true_type {};
Z expects class template as a parameter.
template <template<class> class C>
struct Z<C<int>> {};
Here you are are not specializing any of it's template arguments and trying to pass C<int> which is not a class template (C is a class template and is different than C<int> which is concrete type).
If your class has template parameter which is a class template and you want your class to behave differently for different types passed for the container you probably should do something like:
template<template <typename> class Container,typename Element>
struct MyStruct
{
Container<Element> generic_elements;
// ...
};
template<template <typename> class Container>
struct MyStruct<Container,int>
{
Container<int> special_int_container;
void special_int_things();
//...
};
There is a class template A, which is taking template class for its template parameter.
template <typename T> class A {}
template <typename T> class B {}
int main()
{
A<B<int>>();
return 0;
}
Can class template A deduces its template parameter(B int)'s template parameter(int)?
Or is there the other way to solve this problem? For example,
template <typename T<typename U>> class A {}
You can make A a template template:
template <template <typename> class T, typename Inner>
class A<T<Inner>> {};
template<class>struct inner{};
template<template<class...>class Z, class T, class...Ts>
struct inner<Z<T, Ts...>>{
using type=T;
};
template<class Z>
using inner_t=typename inner<Z>::type;
and inner_t<X> is the first template argument of X if it exists, and a substitution failure otherwise.
What you described is a template template:
template< template<typename> class T > class A {};
note the class before T has to be class, not typename.
Is it possible to specialize this template for any basic_string's?
template<class T> struct X {};
Since basic_string is a template itself, I know this would be a solution:
template <template <class, class, class> class T> struct X {}; template <> struct X<basic_string> {};
However, I would like to know if the language allows to preserve the first template definition, by specializing it somehow for basic_string's only.
Yes:
#include <string>
template <typename> struct X;
template <typename TChar, typename TTraits, typename TAlloc>
struct X<std::basic_string<TChar, TTraits, TAlloc>>
{
// ...
};
Your primary template takes one type parameter, so every specialization must supply one type parameter for X, one way or another.