template template function parameter [duplicate] - c++

This question already has answers here:
How to pass a template function in a template argument list
(2 answers)
Closed 6 years ago.
For the life of me, I can't get this simple piece of arcane template magic to work:
template<typename T, int a, int b>
int f(T v){
return v*a-b; // just do something for example
}
template<typename T, int a, int b, template<typename,int,int> class func>
class C{
int f(){
return func<T,a,b>(3);
}
};
int main(){
C<float,3,2, f> c;
}
Is this possible to do without involving functors?

f is supposed to be a class - you have a function.
See below:
// Class acts like a function - also known as functor.
template<typename T, int a, int b>
class f
{
int operator()(T v)
{
return v*a-b; // just do something for example
}
};
template<typename T, int a, int b, template<typename,int,int> class func>
class C
{
int f()
{
return func<T,a,b>(3);
}
};
int main()
{
C<float,3,2, f> c;
}
... And the adapted version if you need to port legacy code (Adapts the function to a class template):
#include <iostream>
template<typename T, int a, int b>
int f(T v)
{
std::cout << "Called" << std::endl;
return v*a-b; // just do something for example
}
template<typename T, int a, int b, template<typename,int,int> class func>
struct C
{
int f()
{
return func<T,a,b>(3);
}
};
template <class T, int a, int b>
struct FuncAdapt
{
T x_;
template <class U>
FuncAdapt( U x )
: x_( x )
{}
operator int() const
{
return f<T,a,b>( x_ );
}
};
int main()
{
C<float,3,2, FuncAdapt > c;
c.f();
}

You can solve it through a little trickery:
template<typename T, int a, int b>
int f(T v){
return v*a-b; // just do something for example
}
template<typename T, int, int>
using func_t = int (*)(T);
template<typename T, int a, int b, func_t<T, a, b> func>
class C{
int f(){
return func(3);
}
};
C<float,3,2, f<float, 3, 2>> c;
First you need a type-alias for the function (func_t above), and you unfortunately need to duplicate the template arguments in the declaration of c.

No, it's not. Even the syntax:
template <typename T, int a, int b, template <typename, int, int> class func>
^^^^^
shows that an argument for a template template parameter must be a class template.

The reason your compiler is complaining is that you're passing a function (f) as a class to the last template parameter for class C.
Since you cannot pass a function as a template parameter, you should use function pointers or functors. And functors are definitely the cleaner way to do this.
So, although it's possible to achieve what you want without using functors, you really shouldn't try to.
If you want to use function pointers you will be looking at something like this:
template<typename T, int a, int b, int (*func)(T)>
class C{
int f(){
return (*func)(3);
}
};
int main(){
C< float,3,2,&f<float,3,2> > c;
}
In that case I don't think you would be able to eliminate the code duplication in the declaration of c, but I might be wrong.

Related

How to define a class template with reference type template parameter of template template parameter type

I would like to define a class template (hereafter called C) which takes a reference to an object of an to-be instantiated class template (hereafter called S) as template parameter. The objective is that C can be fully instantiated with one template argument.
S is a class template on its own which has one integral type template parameter. The C class template shall be instantiated using a reference to an object of any instantiation of S.
This is what I am trying to achieve:
template<int I> struct S {
int get() { return 42 + I; }
};
// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ my desperate attempt
template< typename S<int I>::template & n>
struct C {
int get() {
return n.get();
}
};
S<42> s;
int main()
{
C<s> c;
return c.get();
}
The compiler I am using supports GNU++11 or older.
In C++17, you might do
template<int I> struct S { int get() { return 42 + I; } };
template <auto& n>
struct C;
template <int I, S<I>& n>
struct C<n>
{
int get() { return n.get(); }
};
S<42> s;
int main()
{
C<s> c;
return c.get();
}
Demo.
Before C++17, template <auto& n> struct C; has to be replaced. for example by
template <typename T, T& n> struct C;
template <typename T, T& n>
struct C;
template <int I, S<I>& n>
struct C<S<I>, n>
{
int get() { return n.get(); }
};
S<42> s;
#define AUTO(x) decltype(x), x
int main()
{
C<S<42>, s> c;
// C<AUTO(s)> c;
return c.get();
}
Demo
There is no way that I know in C++11 that will allow you to change just the template parameters to do what you want. What you can do though is not have a non-type template parameter, but just a type, and add a constructor to C that takes the reference to the desired object as a parameter:
template<typename T>
struct C {
C(T &t): t(t) {}
int get() {
return t.get();
}
private:
T &t;
};
Then you could declare c as follows:
C<decltype(s)> c(s);
However, it is of course not so nice to have to repeat yourself like that, so the trick is to make a templated function that will construct a C of the right type for you:
template<typename T>
C<T> make_C(T &t) {
return C<T>(t);
}
And then you can write:
auto c = make_C(s);
This is not the answer. But maybe this helps somebody who stumbled upon this question or even help somebody to actually find the answer.
In contrast to the original question I added the static member variable S.i.
template<int I> struct S {
static constexpr int i = I;
int get() { return 42 + I; }
};
template<int I, S<I>& n> struct C
{
int get() {
return n.get();
}
};
S<42> s;
int main()
{
C<s.i, s> c;
return c.get();
}
This is not the answer, because still two template arguments are required in order to instantiate the class template C.
This compiles with C++11.

substitutes for enable_if to enable a method for only one template value

I would like to make a template class limit an overloaded method like this example:
template<int N>
class foo {
public:
void add(int a, int* b) {*b = a + N;}
int add(std::enable_if<N == 0, int> a, int b) {return a + b}
}
(Example changed to reflect complications not present in the original example.)
However, I am using Visual Studio, whose support for SFINAE (and thus enable_if) is still not very good. (I'm not sure if it would work in that simple example; in my actual situation I'm using std::enable_if on a class reference and using a member of that class, and it doesn't work.) The answer to this (which has essentially the same error message I got) suggested using tag dispatching as an alternative, but I'm not sure how that would work if I want the function to simply be unavailable at all with those argument types, or if I want to overload a constructor in this manner.
It needs to be made into a function template. And the condition in the enable_if needs to be made dependent on a template parameter of the function template so that it is not substituted into early.
template<int M = N,
class = typename std::enable_if<M == 0>::type>
int add(int a, int b) { return a + b; }
Usually I see std::enable_if used with return type
template<int N>
class foo {
public:
int add(int a)
{return a + N;}
template <int M = N>
typename std::enable_if<M == 0, int>::type add(int a, int b)
{return a + b}
}
This didn't work?
Another way can be the use of a base class (bar, in the following example) that define only add(int, int) and only in the required specialization.
template <int N>
struct bar
{ int add (int a, int b) = delete; };
template <>
struct bar<0>
{ int add (int a, int b) { return a + b; } };
template <int N>
struct foo : public bar<N>
{ using bar<N>::add; void add (int a, int * b) { *b = a + N; } };
int main()
{
foo<0> f0;
foo<1> f1;
int b { 0 };
f0.add(1, &b);
f0.add(1, 2);
f1.add(1, &b);
//f1.add(1, 2); // compilation error
}
Observe that the using bar<N>::add in foo is required because, otherwise, the add(int) in foo hide the add(int, int) in bar.
And that this using impose the int add (int a, int b) = delete; in the generic version of bar<N>.
If the name of the two function is different, say add2() for the version with 2 integer arguments, the example become simply as follows
template <int N>
struct bar
{ };
template <>
struct bar<0>
{ int add2 (int a, int b) { return a + b; } };
template <int N>
struct foo : public bar<N>
{ void add (int a, int * b) { *b = a + N; } };
int main()
{
foo<0> f0;
foo<1> f1;
int b { 0 };
f0.add(1, &b);
f0.add2(1, 2);
f1.add(1, &b);
//f1.add2(1, 2); // compilation error
}
No simple transformation of your code is legal. The signature of methods to template classes must be legal.
template<class D, bool> // false case
struct add_base {
void add(int* a, int b) {*a += b}
D*self(){return static_cast<D*>(this);}
D const*self()const{return static_cast<D const*>(this);}
};
template<class D>
struct add_base<D,true>:add_base<D,false> {
using base=add_base<D,false>;
using base::self;
using base::add; // for overload resolution
int add(int a, int b) {return a + b}
};
template<int N>
class foo: add_base<foo<N>, N==0> {
using base = add_base<foo<N>, N==0>;
template<class D, bool b>
friend class add_base<D, b>;// may be a syntax error here.
public:
using base::add;
};
here I assume the real add wants to use this; in this case use self() in its implementation.
There are other techniques using template parameters with default values, but their legality under a strict reading of the standard is questionable. The problem is the standard mandates all template functions have a valid specialization, and mostnuse of those techniques breaks that rule. There are different readings of the standard under which they may be legal.
You could also wait for c++2a concepts.

How to write a wrapper that keeps rapping the output?

Basically, what I want to do is to hava a wrapper on some abstract class, then have the same wrapper class wrap around the output of any member function of that class. Keep doing that so that all objects are always wrapped.
Like (presudocode)
wrap<set(1..10)> (multiply,2)
(divide,3)
(plus,5)
(inverse)
(collect first 10)
.unwrap()
All lines above except the last line outputs wrap of something. It seems to be meanling less for now, but I believe then we can apply interesting things on it like:
wrap<someClass> dat;
dat.splitIntoThreads(2)
(thingA) .clone()
(thingB) (thing1)
(thingC) (thing2)
(thingD) (thing3)
.nothing() (thing4)
.sync() .exit()
.addMerge()
Here is my code for wrap:
template<class T>
struct wrap{
wrap(){}
wrap(T b){a=b;}
template<class L,class...R>
L operator() (L(T::*f)(R...),R...r){
return a.f(r...);
}
T a;
};
int main(){
wrap<testClass> a;
a(&testClass::f,13,'a');
}
It's working (gcc, c++0x). But when I replace the 6,7th line with the following (to actually wrap the result)
wrap<L> operator() (L(T::*f)(R...),R...r){
return wrap<L>(a.f(r...));
The compiler just sais: creating pointer to member function of non-class type "int".
How can I fix this? Is there any better to do this? Inheritence is one way but since we might have variable instance in one wrap, I think it's not useful.
EDIT
Here's my test class
struct testClass{
int f(int a,char b){
return a+b;
}
};
The reason why I'm using wrap L instead of wrap T is that the return type might not always be T.
You can try something like this:
#include <iostream>
#include <type_traits>
template<class T, bool = false>
struct wrap{
template <typename... Args>
wrap(Args&&... args) : a{std::forward<Args>(args)...} {};
template<class L, class...R>
wrap<L,std::is_fundamental<L>::value> operator() (L(T::*f)(R...),R...r){
return wrap<L,std::is_fundamental<L>::value > {(a.*f)(r...)};
}
T a;
};
template<class T>
struct wrap <T,true>{
template <typename... Args>
wrap(Args&&... args) : a{std::forward<Args>(args)...} {}
template<class L, class...R>
wrap<L,std::is_fundamental<L>::value> operator() (L(*f)(T a, R...), R...r){
return wrap<L,std::is_fundamental<L>::value > {f(a, r...)};
}
T a;
};
class testClass {
int m;
public:
testClass(int _m) : m{_m}{}
int multiAdd(int x, char y) {
m += x + y;
return m;
}
};
int add(int a, char b)
{
return a+b;
}
int main(){
wrap<testClass> a{0};
std::cout << a(&testClass::multiAdd,0,'d')(add,'a').a<<std::endl;
wrap<int, true> b{3};
std::cout << b(add,'a').a<<std::endl;
}
cpp.sh/6icg
It seems the error is in your testclass definition. Please check the below example.
Also, wrap in the operator() can be returned as reference. I don't see any need to create temporaries to be used for () chaining.
template<class T>
struct wrap{
template <typename... Args>
wrap(Args&&... args) : a{std::forward<Args>(args)...} {};
template<class L, class...R>
wrap<T>& operator() (L(T::*f)(R...),R...r){
a.f(r...);
return *this; //returning reference to current wrap object.
}
T a;
};
A test class to accumulate numbers.
class testClass {
int m;
public:
testClass(int _m) : m{_m}{}
int f(int x) {
m += x;
std::cout << ' ' << m;
return m;
}
};
An usage example:
int main(){
wrap<testClass> a{0};
a(&testClass::f,13)(&testClass::f, 11)(&testClass::f,3)(&testClass::f, 21);
}
Output of sum accumulated at each step:
13 24 27 48

Declare a template function as friend

I have a global function like this:
namespace X
{
namespace Y
{
template <R, ...T>
R foo(T&&... args)
{
R r(args...);
return r;
}
}
}
Then in another class A, I want to declare this function foo as friend of A. So I did:
class A
{
template <R, ...T>
friend R X::Y::foo(T&&... args);
A(int x, int y){}
};
Now when, I call X::Y::foo<A>(4, 5) it fails to compile with error that foo can not access the private constructor of A. I am unable to understand the error, how do I declare the foo as friend of A correctly?
Thanks in advance.
After fixing the syntactic issues with template parameters and parameter packs, this seems to work:
namespace X
{
namespace Y
{
template <typename R, typename ...T>
R foo(T&&... args)
{
R r(args...);
return r;
}
}
}
class A
{
template <typename R, typename ...T>
friend R X::Y::foo(T&&... args);
A(int x, int y){}
};
int main()
{
X::Y::foo<A>(1, 2);
}
Here is a live example of the above code compiling.

Partial template specialization of a single method of a bigger class

I have the following class;
template<int N, int M, int K>
class BaumWelch
{
//lots of stuff
const TransitionMatrixTemplate<N, M> randomA()
{ //.... }
}
now I would like to specialize the method randomA for N=1. How can I do it?
I tried following this question: Template specialization of a single method from a templated class, but it doesn't seem to work with partial specialization. This question: C++ partial method specialization seems more relevant, but it suggest specializing the whole class (which is quite big in my case). Is it possible to specialize the whole class, but actually specialize only this one method?
I would like to specialize the method randomA for N=1. How can I do it?
You've discovered that partial specialization for functions is not allowed.
However, you can fully specialize a "detail" implementation of the code.
template<int TheN>
detail_randomA();
const TransitionMatrixTemplate<N, M> randomA()
{
return detail_randomA<N>();
}
And outside the class declaration:
template<int N, int M, int K>
template<int TheN>
BaumWelch<N,M,K>::detail_randomA()
{
//lots of stuff when N != 1
}
template<int N, int M, int K>
template<>
BaumWelch<N,M,K>::detail_randomA<1>()
{
//lots of stuff when N == 1
}
You can't partially specialize function templates, but you can pass the work off to class templates. Here's a fully working example:
#include<iostream>
using namespace std;
// This first template isn't important, it's just the return value from your function
template <int N, int M>
struct TransitionMatrixTemplate {
void print_me() const {
cout << N << ',' << M << endl;
}
};
// We need to announce the existence of the BaumWelch class template early here,
// in order that it can appear in the signature of our impl_randomA class.
template<int N, int M, int K>
struct BaumWelch;
// Now, the first important bit of code. The default implementation
template<int N, int M, int K>
struct impl_randomA {
static TransitionMatrixTemplate<N,M> f(BaumWelch<N,M,K> * This) {
return TransitionMatrixTemplate<N,M>();
}
};
// Next, is the partially specialized version.
template<int M, int K>
struct impl_randomA<1,M,K> {
static TransitionMatrixTemplate<1,M> f(BaumWelch<1,M,K> * This) {
cout << "<Special for N=1> ";
return TransitionMatrixTemplate<1,M>();
}
};
// Finally, The BaumWelch class and its call out to impl_randomA.
template<int N, int M, int K>
struct BaumWelch {
const TransitionMatrixTemplate<N, M> randomA() {
return impl_randomA<N,M,K> :: f(this);
}
};
int main() {
BaumWelch<2,3,4>() . randomA() . print_me();
BaumWelch<1,3,4>() . randomA() . print_me();
}
The short answer is "you don't".
A way to make it easy to do what you want to do (have randomA act differently for N=1) would be to stuff const TransitionMatrixTemplate<N, M> randomA() into a CRTP parent, then partially specialize that for N=1.
template<typename D, int N, int M, int K>
struct Bob_Base {
static_assert( std::is_base_of< D, Bob_Base<D, N, M, K> >::value, "D must be derived from Bob_Base" );
D* self() { return static_cast<D*>(this);
D const* self() const { return static_cast<D*>(this);
const TransitionMatrixTemplate<N, M> randomA()
{
// use self()-> instead of this-> in here to access Bob methods and date
}
};
template<typename D,int M, int K>
struct Bob_Base< D, 1, M, K > {
static_assert( std::is_base_of< D, Bob_Base<D, N, M, K> >::value, "D must be derived from Bob_Base" );
D* self() { return static_cast<D*>(this);
D const* self() const { return static_cast<D*>(this);
const TransitionMatrixTemplate<1, M> randomA()
{ /* N=1 version */ }
};
template<int N, int M, int K>
struct Bob : Bob_Base<Bob<N, M, K>, N, M, K>
{
//lots of stuff, but no TransitionMatrixTemplate
}
this is only important if the code where N==1 cannot compile (or vice versa).