Template class as template class parameter - c++

In this example I create a Functor class taking functions as parameters. The second functor shall take an object of the first functor as template parameter and call a function of the first functor. I am not sure how the template for the second Functor must look.
This is the first Functor, which is working as expected:
typedef float (*pDistanceFu) (float, float);
typedef float (*pDecayFu) (float, float, float);
template <pDistanceFu Dist, pDecayFu Rad, pDecayFu LRate>
class DistFunction {
public:
DistFunction() {}
DistFunction(char *cstr) : name(cstr) {};
char *name;
float distance(float a, float b) { return Dist(a,b); };
float rad_decay(float a, float b, float c) { return Rad(a,b,c); };
float lrate_decay(float a, float b, float c) { return LRate(a,b,c); };
};
Here I create an instance of the functor which is specialized:
DistFunction<foo,bar,foobar> fcn_gaussian((char*)"gaussian");
Here I don't know how the template has to look, to take any type of DistFunction<...> as parameter
template<template<DistFunction> typename = F>
struct functor {
float fCycle;
float fCycles;
functor(float cycle, float cycles) : fCycle(cycle), fCycles(cycles) {}
float operator()(float lrate) {
return (F.lrate_decay)(lrate, fCycle, fCycles);
}
};
How I want to use the second functor:
typedef DistFunction<foo,bar,foobar> gaussian;
void test() {
functor<gaussian> test(0,1);
}
The errors:
error: argument list for class template "DistFunction" is missing
error: expected "class"
error: expected a "," or ">"

template<DistFunction> typename = F
This is an unnamed template template parameter with a single non-type parameter of type DistFunction and default value F. Since DistFunction is not a type (it's a class template) and F does not exist, this makes no sense.
You don't need any template template parameters here. The simple
template<typename F>
struct functor {
should do the job.
If you want to restrict F, that is, only allow it to accept various instantiations of DistFunction and nothing else, you need different language facilities, such as static_assert and/or enable_if. This is only needed for better error messages in case someone imstantiates functor incorrectly. Just use F as if it is a DistFunction.

Try
template<typename F>
struct functor {
float fCycle;
float fCycles;
functor(float cycle, float cycles) : fCycle(cycle), fCycles(cycles) {}
float operator()(float lrate) {
return F((char*)"gaussian").lrate_decay(lrate, fCycle, fCycles);
}
};
LIVE

Related

Function as template parameter, enforce constraint on return type?

I have a templated function which accepts a function as a parameter, like
template <typename Function>
void apply(Function f) {
// do something that invokes f(...)
}
I want to constrain it so that the return type of f() must be some type, say int.
I do not want to constrain the parameters of f (e.g., assume it takes three ints as parameters).
Here's a naive solution, that combines std::enable_if_t, std::is_same_v, decltype and std::declval:
#include <type_traits>
template <
typename Function,
typename = std::enable_if_t<
std::is_same_v<
decltype(std::declval<Function>()(
std::declval<int>(),
std::declval<int>(),
std::declval<int>()
)),
int
>
>
>
void apply(Function f) {
f(1,2,3);
}
int foo(int x, int y, int z);
char bar(int x, int y, int z);
int main()
{
apply(foo);
apply(bar);
}
(live demo)
foo works but bar doesn't.
This should also behave as expected for alternative overloads of foo, because part of the machinery is specifying the types of the arguments we're going to provide to the Function.

How can I concisely write a lot of explicit function template instantiations?

I'm writing a C++ library that contains a lot of function templates I want to explicitly instantiate and export for several type parameters. In my particular case, I have a lot of numeric function templates that I want to separately instantiate and compile for float, double, and long double. They look something like this:
template <typename T>
T calculate_a(T x) { ... }
template <typename T>
T calculate_b(T x, T y) { ... }
// ...
If I have M function templates and N underlying types, then I have M*N explicit instantiations to type out. Is it possible to write these instantiations more concisely?
My current solution is to use a preprocessor macro that performs all instantiations for a given type:
#define EXPLICITLY_INSTANTIATE(T) \
template T calculate_a<T>(T x); \
template T calculate_b<T>(T x, T y); \
// ...
EXPLICITLY_INSTANTIATE(float);
EXPLICITLY_INSTANTIATE(double);
EXPLICITLY_INSTANTIATE(long double);
However, this is suboptimal because it requires me to separately maintain another copy of each function template's signature. Also, if I want to do this in multiple translation units, then I need to separately maintain a list of underlying types in each. (Suppose that C++2a adds a long long double type that I want to support; I'll have to add EXPLICITLY_INSTANTIATE(long long double); to every file.)
Another possible approach is to gather up all of my functions into a (static-only) template class:
template <typename T>
class calculate {
T a(T x) { ... }
T b(T x, T y) { ... }
};
template class calculate<float>;
template class calculate<double>;
template class calculate<long double>;
This solves the first problem of separately maintaining two copies of each signature, but requires me to change each call of calculate_a into calculate::a<T>. It doesn't address the second problem.
You can avoid repeating function signatures by instantiating templates via taking their addresses:
// forward declarations in a header file
template<typename T>
T square(T num);
template<typename T>
T add(T left, T right);
// implementations and instantiations in a single implementation file
template<typename T>
T square(T num) {
return num * num;
}
template<typename T>
T add(T left, T right) {
return left + right;
}
// instantiations for specific types
#include <tuple>
template<typename... Ts>
auto instantiate() {
static auto funcs = std::tuple_cat(std::make_tuple(
add<Ts>,
square<Ts>
)...);
return &funcs;
}
template auto instantiate<int, double>();
The overhead here is a single array of pointers to all instantiated functions, example on godbolt.
This is what X Macros are made for. It works quite simply.
You have a file that contains all of the types you want to apply this to. Let's call it "type_list.inc". It would look like this:
X(float)
X(double)
X(long double)
When you want to perform some operation over that list of types, you #include the file, but around the point of inclusion, you #define the macro X to do the operation you want to perform:
#define X(T) \
template T calculate_a<T>(T x); \
template T calculate_b<T>(T x, T y); \
// ...
#include "type_list.inc"
#undef X
You still have to maintain two sets of function prototypes. But you only need to maintain one list of types.
I haven't clearly communicated my intent in the question. The purpose of my explicit instantiations isn't to limit the types that these functions can be called with, but to inform the compiler to produce executable code for float, double, and long double
Well... if all your types are default constructible (as float, double and long double)... using folding in a template foo() function as follows
template <typename ... Ts>
void foo ()
{ ((calculate_a(Ts{}), calculate_b(Ts{}, Ts{})), ...); }
and calling foo() with desidered types
foo<float, double, long double>();
should work, I suppose.
The following is a full compiling example
template <typename T>
T calculate_a (T x)
{ return x; }
template <typename T>
T calculate_b (T x, T y)
{ return x+y; }
template <typename ... Ts>
void foo ()
{ ((calculate_a(Ts{}), calculate_b(Ts{}, Ts{})), ...); }
int main ()
{
foo<float, double, long double>();
}
Use regular overloading for the types you want and have them call the function template, as in:
float calculate_a(float x) { return calculate_a<float>(x); }
float calculate_b(float x, float y) { return calculate_b<float>(x, y); }
double calculate_a(double x) { return calculate_a<double>(x); }
double calculate_b(double x, double y) { return calculate_b<double>(x, y); }
long double calculate_a(long double x) { return calculate_a<long double>(x); }
long double calculate_b(long double x, long double y) { return calculate_b<long double>(x, y); }

Implicit conversion to template

My example below suggests that implicit conversions from non-template types to template types won't work as seamlessly as those only involving non-template types. Is there a way to make them work nonetheless?
Example:
struct point;
template<unsigned d> struct vec {
vec() { }
// ...
};
template<> struct vec<2> {
vec() { }
vec(const point& p) { /* ... */ } // Conversion constructor
// ...
};
struct point {
operator vec<2>() { return vec<2>(/* ... */); } // Conversion operator
};
template<unsigned d> vec<d> foo(vec<d> a, vec<d> b) {
return vec<d>(/* ... */);
}
template<unsigned d1, unsigned d2>
vec<d1 + d2> bar(vec<d1> a, vec<d2> b) {
return vec<d1 + d2>(/* ... */);
}
int main(int argc, char** argv) {
point p1, p2;
vec<2> v2;
vec<3> v3;
foo(v2, p1);
foo(p2, v2);
foo(p1, p2);
bar(v3, p1);
}
Is there a way to let this code auto-convert from point to vec<2>?
I know I can overload foo and bar to allow for point arguments, delegating to the vec implementation using an explicit conversion. But doing this for all parameter combinations will become tedious, particularly for functions with many such parameters. So I'm not interested in solutions where I have to duplicate code for every parameter combination of every function.
It appears that neither the conversion constructor nor the cast operator are sufficient to achieve this. At least my gcc 4.7.1 reports no matching function call, although it does name the desired function in a notice, stating that ‘point’ is not derived from ‘vec<d>’.
There is no direct way to get the conversion from point to vec<2>, because at the time when the function call foo(v1,p1) is processed, a function foo that expects a vec<2> as second argument does not exist yet. It's just a function template, and in order for this to be instantiated to a foo(const vec<2> &,const vec<2> &), a function call with these exact argument types would have to be given.
In order for the code to work, the compiler would have to guess both how to instantiate the template parameters, and what type the point argument to convert to. This is too much in the general case (although in your particular code it appears simple, because there is no other possible way to interpret the intent of the programmer).
In terms of solving this, the only thing I can think of is to create highly templated conversion functions:
template <typename T>
struct make_vec
{ };
template <unsigned d>
struct make_vec<vec<d>>
{
static constexpr unsigned dim = d;
using type = vec<dim>;
static const type &from(const type &v)
{ return v; }
};
template <>
struct make_vec<point>
{
static constexpr unsigned dim = 2;
using type = vec<dim>;
static type from(const point &p)
{ return type(p); }
};
template <typename T>
typename make_vec<typename std::decay<T>::type>::type make_vec_from(T&& arg)
{ return make_vec<typename std::decay<T>::type>::from(std::forward<T>(arg)); }
And then implement the foo and bar functions as general templates (accepting all kinds of types, not only vec<d>, using make_vec defined above to convert the given types to the right kind of vec<d>):
namespace detail {
/* Your original implementation of foo. */
template<unsigned d> vec<d> foo(vec<d>, vec<d>) {
return vec<d>(/* ... */);
}
}
/* Templated version of foo that calls the conversion functions (which do
nothing if the argument is already a vec<d>), and then calls the
foo() function defined above. */
template <typename T, typename... Ts>
typename make_vec<typename std::decay<T>::type>::type foo(T&& arg, Ts&&... args)
{ return detail::foo(make_vec_from(arg),make_vec_from(args)...); }
In the case of bar you also need a way to calculate the return type, which is vec<d1+d2+d3...>. For this, a sum calculator is required, also templated:
template <typename... Ts>
struct dsum {
static constexpr unsigned value = 0;
};
template <typename T, typename... Ts>
struct dsum<T,Ts...> {
static constexpr unsigned value = make_vec<typename std::decay<T>::type>::dim + dsum<Ts...>::value;
};
Then, the return type of bar() is vec<dsum<T,Ts...>::value>.
A fully working example is here: http://liveworkspace.org/code/nZJYu$11
Not exactly simple, but might be worth it if you really have extremely many different combinations of arguments.

template argument deduction for pointer to member function?

I am trying to build a statically bound delegate class, where the member function is bound at compile time, thereby aiding optimisation.
I have the following code which works exactly how I want it to:
#include <iostream>
namespace thr {
template<typename T, T func>
struct delegate;
template<typename R,
typename C,
typename... A,
R (C::* mem_fun)(A...)>
struct delegate<R(C::*)(A...), mem_fun>
{
delegate(C* obj_)
: _obj(obj_)
{}
R operator()(A... a)
{
return (_obj->*mem_fun)(a...);
}
private:
C* _obj;
};
} // namespace thr
struct foo
{
double bar(int i, int j)
{
return (double)i / (double)j;
}
};
int main()
{
foo f;
typedef thr::delegate<decltype(&foo::bar), &foo::bar> cb;
cb c(&f);
std::cout << c(4, 3);
return 0;
}
However, the usage is not very elegant:
thr::delegate<decltype(&foo::bar), &foo::bar>
I would like to use a function template which deduces the template parameters and returns a delegate instance; something along the lines of (this code does not compile):
template<typename C, typename T, T func>
thr::delegate<T, func> bind(T func, C* obj)
{
return thr::delegate<decltype(func), func>(obj);
}
This would allow for more elegant syntax:
auto cb = bind(&foo::bar, &f);
Is it possible to deduce a non-type parameter in a function template?
Is what I'm trying to achieve even possible?
Would std::function help? http://www2.research.att.com/~bs/C++0xFAQ.html#std-function Your example looks quite close.
I think the compiler supplied STL does pretty horrible things to make it work smoothly. You may want to have a look at as an example before giving up.
Edit: I went out and tried what you try to accomplish. My conclusion is a compile error:
The return type of the bind (delegate) must name the pointer to member because it is your own requirement.
bind should accept the name of the pointer to member to be elegant (i.e. your requirement)
Compiler requires you to not shadow the template parameter with a function parameter or use the name in both parameters and return type.
Therefore one of your requirements must go.
Edit 2: I took the liberty of changing your delegate so bind works as you wish. bind might not be your priority though.
#include <iostream>
namespace thr {
template<typename C,typename R,typename... A>
struct delegate
{
private:
C* _obj;
R(C::*_f)(A...);
public:
delegate(C* obj_,R(C::*f)(A...))
: _obj(obj_),_f(f)
{}
R operator()(A... a)
{
return (_obj->*_f)(a...);
}
};
} // namespace thr
template<class C,typename R,typename... A> thr::delegate<C,R,A...> bind(R(C::*f)(A...),C* obj){
return thr::delegate<C,R,A...>(obj,f);
}
struct foo
{
double bar(int i, int j)
{
return (double)i / (double)j;
}
};
int main()
{
foo f;
auto c = bind(&foo::bar, &f);
std::cout << c(4, 6);
return 0;
}
It is possible to deduce other entities than types in a function signature, but function parameters themselves cannot then be used as template parameters.
Given:
template <size_t I> struct Integral { static size_t const value = I; };
You can have:
template <size_t N>
Integral<N> foo(char const (&)[N]);
But you cannot have:
Integral<N> bar(size_t N);
In the former case, N as the size of the array is part of the type of the argument, in the latter case, N is the argument itself. It can be noticed that in the former case, N appeared in the template parameters list of the type signature.
Therefore, if indeed what you want is possible, the member pointer value would have to appear as part of the template parameter list of the function signature.
There may be a saving grace using constexpr, which can turn a regular value into a constant fit for template parameters:
constexpr size_t fib(size_t N) { return N <= 1 ? 1 : fib(N-1) + fib(N-2); }
Integral<fib(4)> works;
But I am not savvy enough to go down that road...
I do however have a simple question: why do you think this will speed things up ? Compilers are very good at constant propagation and inlining, to the point of being able to inline calls to virtual functions when they can assess the dynamic type of variables at compilation. Are you sure it's worth sweating over this ?

specifying type of a class member in template function

I have this template function:
template <class P>
double Determinant(const P & a, const P & b, const P & c) {
return (b.x-a.x)*(c.y-a.y) - (c.x-a.x)*(b.y-a.y);
}
but I want to avoid forcing the return type to double all the time -- P::x and P::y could be ints too, and I need this function in both situations. Is there a way to specify the type of x and y, something like this?
//doesn't compile; can't deduce template argument for T
template <typename T, class P>
T Determinant(const P & a, const P & b, const P & c) {
return (b.x-a.x)*(c.y-a.y) - (c.x-a.x)*(b.y-a.y);
}
edit: My compiler is VC2005
edit2: sorry to forget to mention: Unfortunately I can't modify the implementation of the structs for P; one of the point types I deal with is MFC/ATL's CPoint, which are hard-coded as { long x; long y; }.
Compiler cannot deduce return-type of function template, from function argument. Type deduction is done with function arguments only.
In C++03, you can define typedef in your class as:
struct A //suppose A is going to be type argument to your function template
{
int x, y; //I'm assuming type of x and y is same!
typedef int value_type; //type of x and y!
};
And then you've to re-write your function as:
template <class P>
typename P::value_type Determinant(const P & a, const P & b, const P & c) {
return (b.x-a.x)*(c.y-a.y) - (c.x-a.x)*(b.y-a.y);
}
Notice the return-type now, its a dependent type. Its :
typename P::value_type
The keyword typename is required here.
Alright, as you said you can't modify your structs, then you can use traits instead. Here is how this can be done:
template<typename T> struct PTraits;
//Suppose this is your type which you can't modify
struct A //A is going to be type argument to your function template
{
long x, y;
};
//specialization: defining traits for struct A
template<>
struct PTraits<A>
{
typedef long value_type; //since type of A::x and A::y is long!
};
And your function template would look like this:
template <class P>
typename PTraits<P>::value_type Determinant(const P & a, const P & b, const P & c) {
return (b.x-a.x)*(c.y-a.y) - (c.x-a.x)*(b.y-a.y);
}
Notice the return-type; its slightly different now:
typename PTraits<P>::value_type
Again, value_type is a dependent name, so the keyword typename is required.
Note that you've to specialize PTraits<> for each type which you pass to the function template, as I did.
I like to use a traits style approach to this:
template<typename T> struct DeterminantReturnInfo {};
template<> struct DeterminantReturnInfo<MyType> { typedef MyOtherType ReturnType; }
template< typename T >
typename DeterminantReturnInfo<T>::ReturnType Determinant( const P & a, const P & B, const P & c)
{
return (b.x-a.x)*(c.y-a.y) - (c.x-a.x)*(b.y-a.y);
}
If you want it to default to double then you just add typedef double ReturnType; to the initial template.
If you're using Visual Studio 2010 or GCC 4.5+, you can use the trailing return type form:
template<class P>
auto fun(const P& a) -> decltype(a.x + a.y){
return a.x + a.y;
}
Thanks to decltype we automatically get the right return type. Also, the computation is still only done once in the body, not in the trailing return.
Check your return Type its of type member variable x/y . You might not returning so type T.