Instantiating template classes with template parameters - c++

I have three classes:
//Template class for function 1
template<class P> class wrap4{
P p;
public:
wrap4(P&& p1) : p(std::forward<P>(p1)) {}
double f(double x){
return p.FN(x);
}
};
//Simple concrete parameter
struct Parameter{
double FN(double x){
return x;
}
};
//Method used in the program
template<class Function> class B {
Function F;
public:
B(Function && f) : F(std::forward<Function>(f)) {}
double use(double x){
return F.f(x);
}
};
template<class Function> B<Function> make_B(Function && F){ return B<Function>{std::forward<Function>(F)}; }
template<class P> B<P> make_wrap4(P && F){ return B<P>{std::forward<P>(F)}; }
Basically, I want to plug wrap4 into B, but to do so I have to instantiate it with Parameter. I've tried the following:
auto A = make_B(make_wrap4{Parameter p});
but this doesn't work, I get the compiler error
error: conversion from 'B<B<Parameter> >' to non-scalar type 'B<wrap4<Parameter> >' requested
Of course, this is a silly example because I know I can just implement B with Parameter, but of course I'm trying to do something more complicated in the long run where I really need a B to take a template class which doesn't admit a default constructor as an argument.
Do I need to implement a template template parameter here?

You have a copy&paste error you should be able to spot from the error message:
template<class P> B<P> make_wrap4(P && F){ return B<P>{std::forward<P>(F)}; }
should be
template<class P> wrap4<P> make_wrap4(P && F){ return wrap4<P>{std::forward<P>(F)}; }
// ^^ here ^^ and here
and then you should call make_wrap4 like a function, i.e. not with an initializer list.
A little sidenote: you don't have three classes, you have one class and two class templates. It's also not a template class, as the comment states for wrap4.
wrap4 is a class template.
wrap4<int> and wrap4<Parameter> are classes, which you get by instantiating the class template. Some people would call such classes template class as well.

Related

Passing unique_ptr<Derived<T>> to a function

I need to pass a unique pointer to a derived template class to a function that takes a unique base template class, like this:
template <typename T>
class Base {};
template <typename T>
class Derived : public Base<T> {};
template <typename T>
void foo(std::unique_ptr<Base<T>>){}
//or
template <typename T>
class MyClass{
public:
MyClass(std::unique_ptr<Base<T>> arg) : _arg(std::move(arg)) {}
private:
std::unique_ptr<Base<T>> _arg;
};
int main()
{
auto b = make_unique<Derived<int>>();
foo(std::move(b));
MyClass mc(std::move(b))
}
Why is this not working and how can I fix it?
I get an error:
'void foo1<T>(std::unique_ptr<Base<T>,std::default_delete<Base<T>>>)': cannot convert argument 1 from 'std::unique_ptr<Derived<int>,std::default_delete<Derived<int>>>' to 'std::unique_ptr<Base<T>,std::default_delete<Base<T>>>'
but it work
auto derived = std::make_unique<Derived<int>>();
std::unique_ptr<Base<int>> base = std::move(derived);
C++ doesn't deduce template arguments in this situation. You can specify <int>, and that will succeed.
foo<int>(std::move(b)); // fine
MyClass<int> mc(std::move(b)); // fine
See it on coliru
You can't have template argument deduction also consider implicit conversions, at least not in most situations. Normally the argument type must match the parameter type exactly for deduction of a template argument to be possible (in this case to deduce T), but std::unique_ptr<Base<int>> and std::unique_ptr<Dervived<int>> are not the same type.
As the other answer suggests you can explicitly specify the template argument instead of trying to have it be deduced.
If you want to automate this without having to add anything to Derived or Base you can however make use of one of the exceptions to the general rule above. If the template parameter is a reference-to or pointer-to base of the argument type, then it may (with certain conditions) still be used for deduction:
// Here an exception to the deduction rules applies
// and `Base<T>*` can be deduced against a pointer `X*`
// if `X` is (uniquely) derived from a `Base<T>`
template<typename T>
auto as_base_ptr(Base<T>* p){
return p;
}
template<typename X>
auto to_base_unique_ptr(std::unique_ptr<X> p) {
using base_type = std::remove_pointer_t<decltype(as_base_ptr(std::declval<X*>()))>;
return std::unique_ptr<base_type>(std::move(p));
}
template <typename T>
void foo(std::unique_ptr<Base<T>>){
}
template <typename X>
void foo(std::unique_ptr<X> p){
foo(to_base_unqiue_ptr(std::move(p)));
}
But even simpler you can ask yourself whether you really need to have the function foo take std::unique_ptr<Base<T>> specifically (e.g. because you need access to T) or whether std::unique_ptr<X> wouldn't already be enough.

Timing of C++template specialization and constexpr function execution [duplicate]

Note: this seems to be a repost of a problem: C++ - Overload templated class method with a partial specilization of that method
I have boiled down a problem I am having with C++ template specialization down to a simple case.
It consists of a simple 2-parameter template class Thing, where I would like to specialize Thing<A,B>::doSomething() for B=int.
#include <cstdio>
// A 3-parameter template class.
template <class A, class B>
class Thing
{
public:
Thing(A a, B b) : a_(a), b_(b) {}
B doSomething();
private:
A a_;
B b_;
};
// The generic case works as expected.
template <class A, class B>
B Thing<A,B>::doSomething()
{
return b_;
}
// This specialization does not work!
template <class A>
int Thing<A,int>::doSomething()
{
return b_+1;
}
int main() {
// Setup our thing.
Thing<double,int> thing(1.0,2);
// This doesn't compile - but works with the generic case.
printf("Expecting 3, and getting %i\n", thing.doSomething());
// Clean up.
return 0;
}
Unfortunately, g++ exits with the error:
partial_specialization.cpp:30: error: invalid use of incomplete type ‘class Thing<A, int>’
partial_specialization.cpp:8: error: declaration of ‘class Thing<A, int>’
The clang++ compiler is a bit more verbose, but has the same problem:
partial_specialization.cpp:30:19: error: nested name specifier 'Thing<A, int>::' for declaration does not
refer into a class, class template or class template partial specialization
int Thing<A,int>::doSomething()
~~~~~~~~~~~~~~^
partial_specialization.cpp:32:12: error: use of undeclared identifier 'b_'
return b_+1;
^
2 errors generated.
I have read and understood that partial template specializations on functions aren't allowed - but I thought I was partially specializing over classes of Thing in this case.
Any ideas?
What I did: A workaround, as determined from the link provided by the accepted answer:
template< class T >
inline T foo( T const & v ) { return v; }
template<>
inline int foo( int const & v ) { return v+1; }
// The generic case works as expected.
template <class A, class B>
B Thing<A,B>::doSomething()
{
return foo(b_);
}
Partial specialization of a function template, whether it is member function template or stand-alone function template, is not allowed by the Standard:
template<typename T, typename U> void f() {} //okay - primary template
template<typename T> void f<T,int>() {} //error - partial specialization
template<> void f<unsigned char,int>() {} //okay - full specialization
But you can partially specialize the class template itself. You can do something like this:
template <class A>
class Thing<A,int> //partial specialization of the class template
{
//..
int doSomething();
};
template <class A>
int Thing<A,int>::doSomething() { /* do whatever you want to do here */ }
Note that when you partially specialize a class template, then the template parameter-list of member function (in its definition outside the class), must match the template parameter list of the class template partial specialization. That means, for the above partial specialization of the class template, you cannot define this:
template <class A>
int Thing<A,double>::doSomething(); //error
Its not allowed, because the template parameter-list in function definition didn't match the template parameter-list of the class template partial specialization. §14.5.4.3/1 from the Standard (2003) says,
The template parameter list of a member of a class template partial specialization shall match the template parameter list of the class template partial specialization.[...]
For more on this, read my answer here:
C++ - Overload templated class method with a partial specilization of that method
So what is the solution? Would you partially specialize your class along with all the repetitive work?
A simple solution would be work delegation, instead of partially specializing the class template. Write a stand-alone function template and specialize this as:
template <class B>
B doTheActualSomething(B & b) { return b; }
template <>
int doTheActualSomething<int>(int & b) { return b + 1; }
And then call this function template from doSomething() member function as:
template <class A, class B>
B Thing<A,B>::doSomething() { return doTheActualSomething<B>(b_); }
Since in your particular case, doTheActualSomething needs to know the value of only one member, namely b_, the above solution is fine, as you can pass the value to the function as argument whose type is the template type argument B, and specialization for int is possible being it full-specialization.
But imagine if it needs to access multiple members, type of each depends on the template type argument-list, then defining a stand-alone function template wouldn't solve the problem, because now there will be more than one type argument to the function template, and you cannot partially specialize the function for just, say, one type (as its not allowed).
So in this case you can define a class template instead, which defines a static non-template member function doTheActualSomething. Here is how:
template<typename A, typename B>
struct Worker
{
B doTheActualSomething(Thing<A,B> *thing)
{
return thing->b_;
}
};
//partial specialization of the class template itself, for B = int
template<typename A>
struct Worker<A,int>
{
int doTheActualSomething(Thing<A,int> *thing)
{
return thing->b_ + 1;
}
};
Notice that you can use thing pointer to access any member of the class. Of course, if it needs to access private members, then you've to make struct Worker a friend of Thing class template, as:
//forward class template declaration
template<typename T, typename U> struct Worker
template <class A, class B>
class Thing
{
template<typename T, typename U> friend struct Worker; //make it friend
//...
};
Now delegate the work to the friend as:
template <class A, class B>
B Thing<A,B>::doSomething()
{
return Worker<A,B>::doTheActualSomething(this); //delegate work
}
Two points to be noted here:
In this solution, doTheActualSomething is not a member function template. Its not enclosing class which is template. Hence we can partially specialize the class template anytime, to get the desired effect of the partial member function template specialization.
Since we pass this pointer as argument to the function, we can access any member of the class Thing<A,B>, even private members, as Worker<T,U> is also a friend.
Complete online demo : http://www.ideone.com/uEQ4S
Now there is still a chance of improvement. Now all instantiations of Worker class template are friends of all instantiation of Thing class template. So we can restrict this many-to-many friendship as:
template <class A, class B>
class Thing
{
friend struct Worker<A,B>; //make it friend
//...
};
Now only one instantiation of Worker class template is a friend of one instantiation of Thing class template. That is one-to-one friendship. That is, Worker<A,B> is a friend of Thing<A,B>. Worker<A,B> is NOT a friend of Thing<A,C>.
This change requires us to write the code in somewhat different order. See the complete demo, with all the ordering of class and function definitions and all:
http://www.ideone.com/6a1Ih
This is a very often found problem, and there is a surprisingly simple solution. I will show it in an artificial example, because it's more clearer than to use your code, and you will have to understand it to adapt it to your code
template<typename A, typename B>
struct TwoTypes { };
template<typename A, typename B>
struct X {
/* forwards ... */
void f() { fImpl(TwoTypes<A, B>()); }
/* special overload for <A, int> */
template<typename A1>
void fImpl(TwoTypes<A1, int>) {
/* ... */
}
/* generic */
template<typename A1, typename B1>
void fImpl(TwoTypes<A1, B1>) {
/* ... */
}
};
Explicitly specializing functions is never (almost never?) the right way. In my work as a programmer, I've never explicitly specialized a function template. Overloading and partial ordering is superior.

C++: Function pointer as Template argument instead of functor

I have been trying to create this class which can either use the default functor as an argument or the user can provide one if he wants. But I am unable to pass function pointer as my template argument. Can you please help me in understanding what I am missing.
template <typename T>
struct CheckFunctor
{
bool operator()(T obj)
{
return true;
}
};
template <typename _Ty,
class _Pr = CheckFunctor<_Ty>
>
class MyClass
{
typedef _Ty mapped_type;
typedef _Pr CanBeCleaned_type;
_Ty data;
CanBeCleaned_type predicate;
public:
void SomeMethod()
{
if( predicate(data))
{
std::cout << "Do something";
}
}
MyClass(_Ty timeOutDuration, _Pr pred = _Pr())
: data( timeOutDuration), predicate( pred)
{}
};
template< typename T>
struct CheckEvenFunctor
{
bool operator()(T val)
{
return (val%2 == 0);
}
};
bool CheckEven( int val)
{
return (val%2 == 0);
}
int main()
{
//Usage -1
MyClass<int> obj1( 5);
//Usage- 2
MyClass< int, CheckEven> obj2(6, CheckEven); //Error: 'CheckEven' is not a valid template type argument for parameter '_Pr'
//Usage -3
MyClass<int, CheckEvenFunctor<int>>( 7);
}
You are trying to pass CheckEven as a type parameter even though CheckEven is not a type but a function (of type bool(int)). You should define the type as a pointer to the type of function that you are passing. decltype is handy here:
MyClass< int, decltype(&CheckEven)> obj2(6, CheckEven);
You can also create a factory function and let the compiler deduce the template parameters:
template<class T, class F>
MyClass<T, F> makeClass(T timeOutDuration, F pred) {
return {timeOutDuration, pred};
}
auto obj2 = makeClass(6, CheckEven);
It is possible to allow a template parameter to be a function, but your MyClass is expecting the second argument to be a type, not a function. You might think that template specialization could be used to allow you to define MyClass to also take a function in the second template argument, but it won't work. Template specialization allows you to modify the behavior of MyClass for particular types that are passed as template arguments, but those types must still match the template definition of MyClass, which is that the two arguments are types.
You could modify the type of MyClass you are instantiating by making the second argument a function pointer type as suggested in a different answer, but you would lose the advantage of template expansion making your calls to functions inline. Another solution would be to create a helper class that will convert your function into a functor, and use that to create your MyClass instance.
template <bool P (int)>
struct F {
bool operator()(int obj) { return P(obj); }
};
//...
MyClass<int, F<CheckEven> > obj2(6);

Understanding (simple?) C++ Partial Template Specialization

Note: this seems to be a repost of a problem: C++ - Overload templated class method with a partial specilization of that method
I have boiled down a problem I am having with C++ template specialization down to a simple case.
It consists of a simple 2-parameter template class Thing, where I would like to specialize Thing<A,B>::doSomething() for B=int.
#include <cstdio>
// A 3-parameter template class.
template <class A, class B>
class Thing
{
public:
Thing(A a, B b) : a_(a), b_(b) {}
B doSomething();
private:
A a_;
B b_;
};
// The generic case works as expected.
template <class A, class B>
B Thing<A,B>::doSomething()
{
return b_;
}
// This specialization does not work!
template <class A>
int Thing<A,int>::doSomething()
{
return b_+1;
}
int main() {
// Setup our thing.
Thing<double,int> thing(1.0,2);
// This doesn't compile - but works with the generic case.
printf("Expecting 3, and getting %i\n", thing.doSomething());
// Clean up.
return 0;
}
Unfortunately, g++ exits with the error:
partial_specialization.cpp:30: error: invalid use of incomplete type ‘class Thing<A, int>’
partial_specialization.cpp:8: error: declaration of ‘class Thing<A, int>’
The clang++ compiler is a bit more verbose, but has the same problem:
partial_specialization.cpp:30:19: error: nested name specifier 'Thing<A, int>::' for declaration does not
refer into a class, class template or class template partial specialization
int Thing<A,int>::doSomething()
~~~~~~~~~~~~~~^
partial_specialization.cpp:32:12: error: use of undeclared identifier 'b_'
return b_+1;
^
2 errors generated.
I have read and understood that partial template specializations on functions aren't allowed - but I thought I was partially specializing over classes of Thing in this case.
Any ideas?
What I did: A workaround, as determined from the link provided by the accepted answer:
template< class T >
inline T foo( T const & v ) { return v; }
template<>
inline int foo( int const & v ) { return v+1; }
// The generic case works as expected.
template <class A, class B>
B Thing<A,B>::doSomething()
{
return foo(b_);
}
Partial specialization of a function template, whether it is member function template or stand-alone function template, is not allowed by the Standard:
template<typename T, typename U> void f() {} //okay - primary template
template<typename T> void f<T,int>() {} //error - partial specialization
template<> void f<unsigned char,int>() {} //okay - full specialization
But you can partially specialize the class template itself. You can do something like this:
template <class A>
class Thing<A,int> //partial specialization of the class template
{
//..
int doSomething();
};
template <class A>
int Thing<A,int>::doSomething() { /* do whatever you want to do here */ }
Note that when you partially specialize a class template, then the template parameter-list of member function (in its definition outside the class), must match the template parameter list of the class template partial specialization. That means, for the above partial specialization of the class template, you cannot define this:
template <class A>
int Thing<A,double>::doSomething(); //error
Its not allowed, because the template parameter-list in function definition didn't match the template parameter-list of the class template partial specialization. §14.5.4.3/1 from the Standard (2003) says,
The template parameter list of a member of a class template partial specialization shall match the template parameter list of the class template partial specialization.[...]
For more on this, read my answer here:
C++ - Overload templated class method with a partial specilization of that method
So what is the solution? Would you partially specialize your class along with all the repetitive work?
A simple solution would be work delegation, instead of partially specializing the class template. Write a stand-alone function template and specialize this as:
template <class B>
B doTheActualSomething(B & b) { return b; }
template <>
int doTheActualSomething<int>(int & b) { return b + 1; }
And then call this function template from doSomething() member function as:
template <class A, class B>
B Thing<A,B>::doSomething() { return doTheActualSomething<B>(b_); }
Since in your particular case, doTheActualSomething needs to know the value of only one member, namely b_, the above solution is fine, as you can pass the value to the function as argument whose type is the template type argument B, and specialization for int is possible being it full-specialization.
But imagine if it needs to access multiple members, type of each depends on the template type argument-list, then defining a stand-alone function template wouldn't solve the problem, because now there will be more than one type argument to the function template, and you cannot partially specialize the function for just, say, one type (as its not allowed).
So in this case you can define a class template instead, which defines a static non-template member function doTheActualSomething. Here is how:
template<typename A, typename B>
struct Worker
{
B doTheActualSomething(Thing<A,B> *thing)
{
return thing->b_;
}
};
//partial specialization of the class template itself, for B = int
template<typename A>
struct Worker<A,int>
{
int doTheActualSomething(Thing<A,int> *thing)
{
return thing->b_ + 1;
}
};
Notice that you can use thing pointer to access any member of the class. Of course, if it needs to access private members, then you've to make struct Worker a friend of Thing class template, as:
//forward class template declaration
template<typename T, typename U> struct Worker
template <class A, class B>
class Thing
{
template<typename T, typename U> friend struct Worker; //make it friend
//...
};
Now delegate the work to the friend as:
template <class A, class B>
B Thing<A,B>::doSomething()
{
return Worker<A,B>::doTheActualSomething(this); //delegate work
}
Two points to be noted here:
In this solution, doTheActualSomething is not a member function template. Its not enclosing class which is template. Hence we can partially specialize the class template anytime, to get the desired effect of the partial member function template specialization.
Since we pass this pointer as argument to the function, we can access any member of the class Thing<A,B>, even private members, as Worker<T,U> is also a friend.
Complete online demo : http://www.ideone.com/uEQ4S
Now there is still a chance of improvement. Now all instantiations of Worker class template are friends of all instantiation of Thing class template. So we can restrict this many-to-many friendship as:
template <class A, class B>
class Thing
{
friend struct Worker<A,B>; //make it friend
//...
};
Now only one instantiation of Worker class template is a friend of one instantiation of Thing class template. That is one-to-one friendship. That is, Worker<A,B> is a friend of Thing<A,B>. Worker<A,B> is NOT a friend of Thing<A,C>.
This change requires us to write the code in somewhat different order. See the complete demo, with all the ordering of class and function definitions and all:
http://www.ideone.com/6a1Ih
This is a very often found problem, and there is a surprisingly simple solution. I will show it in an artificial example, because it's more clearer than to use your code, and you will have to understand it to adapt it to your code
template<typename A, typename B>
struct TwoTypes { };
template<typename A, typename B>
struct X {
/* forwards ... */
void f() { fImpl(TwoTypes<A, B>()); }
/* special overload for <A, int> */
template<typename A1>
void fImpl(TwoTypes<A1, int>) {
/* ... */
}
/* generic */
template<typename A1, typename B1>
void fImpl(TwoTypes<A1, B1>) {
/* ... */
}
};
Explicitly specializing functions is never (almost never?) the right way. In my work as a programmer, I've never explicitly specialized a function template. Overloading and partial ordering is superior.

Don't have access to template template parameters

Why can't I do this:
template<template<class E>class Derived>
struct X
{
static void f()
{
Derived<E>::value;
}
};
The problem that I have is that I cannot compile this code for the reason that I'm getting an error saying that param E hasn't been declared. Is there a way that I can use this formal param or not?
Parameters of template template parameters don't get arguments, and therefore don't usually have names. Partial specialization is the exception to this rule. Try this instead:
template<class> // Derived<E> is only only parameter
struct X; // but you actually need two parameters, Derived and E
template< template <class> class Derived, class E >
struct X< Derived< E > > // so use partial specialization.
{
static void f()
{
Derived<E>::value; // only reason to want this is to
Derived<int>::value; // use different specializations
}
};
Of course, if you don't need to re-specialize on Derived< something_else >, just ignore the fact that Derived<E> is a template specialization:
template<class Derived>
struct X
{
static void f()
{
Derived::value;
}
};
X< my_class< something > > my_x; // a specialized class template is a class
Your template parameter Derived is a template itself, E is its formal parameter.
You need to pass a value for it, too.
Maybe you need the following:
template<template<class E>class Derived, class T>
struct X
{
static void f()
{
Derived<T>::value;
}
};
You can't use that parameter because it is just there to mean that Derived is a template with exactly one type argument.
You'd call f like this:
template <class T>
struct ZZZ {};
X<ZZZ>::f();
^^^
Note that there is no E in this instantiation.
Unless there is a reason to use template templates, you could just use a regular template, else you'll need to pass E as a separate argument, making the call look like this:
X<ZZZ, int>::f();
You just have your syntax a bit muddled.
template<class E>
struct X
{
static void f()
{
Derived<E>::value;
}
}
should work fine.