Unrolling loops using templates in C++ with partial specialization - c++

I'm trying to use templates to unroll a loop in C++ as follows.
#include <iostream>
template< class T, T i >
struct printDown {
static void run(void) {
std::cout << i << "\n";
printDown< T, i - 1 >::run();
}
};
template< class T >
struct printDown< T, 0 > {
static void run(void) {
std::cout << 0 << "\n";
}
};
int main(void) {
printDown< int, 10 >::run();
return 0;
}
When I compile w/ g++ 3.4.4 in Cygwin, I get the following error.
tmp.cpp:12: error: type T' of
template argument0' depends on
template parameter(s)
What am I doing wrong? Do I need to somehow annotate the 0 to say that it's of type T?
Thanks in advance.

Have you tried int i instead of T i?

Why this happens? From 14.5.5/8,
— 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 ]
Therefore when you apply partial specialization, the type of 0 is T (dependent on a parameter of the specialization). There are two choices, one is to make it none dependent, e.g., change T i to int i, and second is to apply explicit specialization rather than partial specialization.
Both solutions have been given out by others, so I'm not gonna to repost them here. At least you know the reason. It's defined by standard.

As pointed out by phooji your implementation suffers from a small issue: it quickly generates a long list of calls, which will make compilers choke quickly.
You could work around this by implementing a slightly more complicated version, using binary decomposition. I'll make it generic on a functor too, cause I am lazy.
// Signature
template <Functor F, unsigned N>
struct UnrolledLoop;
We need a helper template, which keeps an offset of the parameter to pass
template <Functor F, unsigned N, unsigned OffSet>
struct UnrolledImpl;
template <Functor F, unsigned OffSet>
struct UnrolledImpl<F, 0, OffSet>
{
static F run(F f) { return f; }
};
template <Functor F, unsigned OffSet>
struct UnrolledImpl<F, 1, OffSet>
{
static F run(F f) { f(OffSet); return f; }
};
template <Functor F, unsigned N, unsigned OffSet>
struct UnrolledImpl
{
static F run(F f) {
F f2 = UnrolledImpl<F, N/2, OffSet>::run(f);
return UnrolledImpl<F, N - N/2, OffSet + N/2>::run(f2);
}
};
And you can implement UnrolledLoop simply:
template <Functor F, unsigned N>
struct UnrolledLoop
{
static F run(F f) { return UnrolledImpl<F, N, 0>::run(f); }
}
Note that you could provide specialization for more values of N (3, 4 for example) to be nicer on the compiler.

What about adding this to your example:
template struct printDown< int, 0 >{
static void run(void) {
std::cout << 0 << "\n";
} };
The compiler cannot cast 0 to int automatically without knowing T's type in advance.

Just found this out. Apparently one can do something like this.
template< class T, T i, bool b = (i == 0) >
struct printDown {
static void run(void) {
std::cout << i << "\n";
printDown< T, i - 1 >::run();
}
};
template< class T, T i >
struct printDown< T, i, true > {
static void run(void) {
std::cout << 0 << "\n";
}
};
I had no idea that could be done. Very Prologish & very nice.

You can make the parameter a type parameter to work this around
template< bool > struct bool_ { };
template< class T, T i, typename = bool_<true> >
struct printDown {
static void run(void) {
std::cout << i << "\n";
printDown< T, i - 1 >::run();
}
};
template< class T, T i >
struct printDown< T, i, bool_<i == 0> > {
static void run(void) {
std::cout << 0 << "\n";
}
};
int main(void) {
printDown< int, 10 >::run();
return 0;
}
This way you can specify any conditions you want in the partial specializations.

Related

Concept requires parameter list with template parameters

What I'm trying to do is find a clean way to implement a concept for a callable object that takes in a single parameter of type either int or long.
My first attempt was to create a single concept with a secondary template parameter to ensure the parameter type is either int or long. The problem with this approach, as seen in the example below, is that applications of this concept can't infer template parameters. For example, the usages of call() below require that template parameters be explicitly listed out.
// https://godbolt.org/z/E519s8Pso
//
#include <concepts>
#include <iostream>
// Concept for a callable that can take a single parameter or either int or long.
template<typename T, typename P>
concept MySpecialFunction =
(std::same_as<P, int> || std::same_as<P, long>)
&& requires(T t, P l) {
{ t(l) } -> std::same_as<decltype(l)>;
};
// T must be callable with 1 parameter that is either int or long!
template<typename T, typename P>
requires MySpecialFunction<T, P>
decltype(auto) call(T t) {
return t(2);
}
// Test
int square_int(int num) {
return num * num;
}
long square_long(long num) {
return num * num;
}
int main() {
std::cout << call<decltype(square_int), int>(square_int) << std::endl;
std::cout << call<decltype(square_long), long>(square_long) << std::endl;
return 0;
}
My second attempt was to explode out the concept to one for int and one for long, then combine them together in a third concept. In this version, the usages of call() below don't require that template parameters be explicitly listed out, but the concept is more verbose. Imagine how something like this would look if there were more than 20 types instead of just 2.
// https://godbolt.org/z/hchT11rMx
//
#include <concepts>
#include <iostream>
// Concept for a callable that can take a single parameter or either int or long.
template<typename T>
concept MySpecialFunction1 = requires(T t, int i) {
{ t(i) } -> std::same_as<decltype(i)>;
};
template<typename T>
concept MySpecialFunction2 = requires(T t, long l) {
{ t(l) } -> std::same_as<decltype(l)>;
};
template<typename T>
concept MySpecialFunction = MySpecialFunction1<T> || MySpecialFunction2<T>;
// T must be callable with 1 parameter that is either int or long!
template<MySpecialFunction T>
decltype(auto) call(T t) {
return t(2);
}
// Test
int square_int(int num) {
return num * num;
}
long square_long(long num) {
return num * num;
}
int main() {
std::cout << call(square_int) << std::endl;
std::cout << call(square_long) << std::endl;
return 0;
}
Is there anyway to have the conciseness / easy of understanding that the first example gives without the compiler losing the ability to infer template parameters as happens in the second example?
Since you have the types int and long baked into the concept, why don't you use something like this:
//true if Fn accepts one parameter (int or long) and have the same type as the result
template <typename Fn>
concept MySpecialFunction = requires (Fn fn) {
requires
std::same_as<int, decltype(fn(0))> ||
std::same_as<long, decltype(fn(0L))>;
};
template <MySpecialFunction Fn>
decltype(auto) call(Fn fn)
{
//think about what happens if Fn is square_long
//doesn't the type of the value (int) gets converted to long?
//that raises the question what your main purpose is
return fn(2);
}
See: https://godbolt.org/z/Y7vTrPoP5
Maybe you also want to have a look at:
https://en.cppreference.com/w/cpp/concepts/invocable
https://en.cppreference.com/w/cpp/utility/functional/invoke
After some browsing around, I came across https://stackoverflow.com/a/43526780/1196226 and https://stackoverflow.com/a/22632571/1196226. I was able to utilize these answers to build out a solution that can apply concepts to parameters concisely and without the compiler losing the ability to infer template parameters.
// https://godbolt.org/z/nh8nWxhzK
//
#include <concepts>
#include <iostream>
template <std::size_t N, typename T0, typename ... Ts>
struct typeN { using type = typename typeN<N-1U, Ts...>::type; };
template <typename T0, typename ... Ts>
struct typeN<0U, T0, Ts...> { using type = T0; };
template <std::size_t, typename F>
struct argN;
template <std::size_t N, typename R, typename ... As>
struct argN<N, R(*)(As...)> { using type = typename typeN<N, As...>::type; }; // needed for std::integral<>
template <std::size_t N, typename R, typename ... As>
struct argN<N, R(As...)> { using type = typename typeN<N, As...>::type; }; // needed for std::is_integeral_v<>
template <typename F>
struct returnType;
template <typename R, typename ... As>
struct returnType<R(*)(As...)> { using type = R; }; // works for std::integral<> / std::same_as<>
template <typename R, typename ... As>
struct returnType<R(As...)> { using type = R; }; // needed for std::is_integeral_v<>
template<typename Fn>
concept MySpecialFunction =
(std::same_as<typename argN<0U, Fn>::type, int> || std::same_as<typename argN<0U, Fn>::type, long>)
&& std::same_as<typename returnType<Fn>::type, typename argN<0U, Fn>::type>;
template<MySpecialFunction Fn>
decltype(auto) call(Fn fn) {
return fn(2);
}
// Test
int square_int(int num) {
return num * num;
}
long square_long(long num) {
return num * num;
}
static_assert( std::is_integral_v<typename argN<0U, decltype(square_int)>::type> );
static_assert( std::is_integral_v<typename returnType<decltype(square_int)>::type> );
static_assert( std::is_integral_v<typename argN<0U, decltype(square_long)>::type> );
static_assert( std::is_integral_v<typename returnType<decltype(square_long)>::type> );
int main() {
std::cout << call(square_int) << std::endl;
std::cout << call(square_long) << std::endl;
return 0;
}

Avoiding code duplication for runtime-to-compile-time numeric parameter translation

Suppose we have function such as
template <typename T, unsigned N> void foo();
and for simplicity assume that we know that only (constant) values N_1, N_2 ... N_k are valid for N.
Now, suppose I want to make that compile-time parameter a run-time one, using foo() as a black-box, i.e. implement:
template <typename T> void foo(unsigned n);
by making foo<,>() calls. How should I go about doing that? Obviously, I can write:
template <typename T> void foo(unsigned n) {
switch(n) {
case N_1 : foo<T, N_1>(); break;
case N_2 : foo<T, N_2>(); break;
// etc. etc.
case N_k : foo<T, N_k>(); break;
}
}
... but this makes me feel all dirty. I could use a MAP() meta-macro to generate these k lines, I suppose; but can I do anything better and less-macroish to achieve the same? Is it possible to write something like the above that's general, and works for every variadic template and a fixed sequence of constant values?
Notes:
C++11/14/17-specific suggestions are obviously welcome.
The N's are not necessarily contiguous, nor small, nor sorted. e.g. suppose N_2 = 123456789 and N_5 = 1.
You could make a function pointer table:
using F = void(*)();
template <class T, class >
struct Table;
template <class T, size_t... Is>
struct Table<T, std::index_sequence<Is...> > {
static constexpr F fns[] = {
foo<T, Is>...
};
};
template <class T, size_t... Is>
constexpr F Table<T, std::index_sequence<Is...> >::fns[sizeof...(Is)];
And then just invoke the one you want:
template <class T, size_t N>
struct MakeTable : Table<T, std::make_index_sequence<N>> { };
template <typename T>
void foo(unsigned n) {
MakeTable<T, MaxN>::fns[n]();
}
If the N_ks aren't contiguous, then we can use a lambda for inline parameter unpacking:
template <class T>
void foo(unsigned n) {
using seq = std::index_sequence<N_1, N_2, ..., N_k>;
indexer(seq)([n](auto i){
if (n == i) {
f<T, i>();
}
});
}
If the above is too slow, then I guess just manually build a std::unordered_map<unsigned, void(*)()> or something.
In these kind of situations I like to build a static table of function pointers, with a dynamic parameter deciding which one to dispatch to. Below is an implementation that achieves this, in the function foo_dynamic. To this function, you specify the maximum value of N you'd like to support, and it builds a static table of function pointers using some recursive templates. You then dereference into this table with your dynamic parameter.
using ftype = void (*)();
template <typename T, unsigned N> void foo()
{
std::cout << N << std::endl;
}
template <typename T, unsigned max>
struct TablePopulator
{
static void populateFTable(ftype* table)
{
table[max] = foo<T,max>;
TablePopulator<T,max-1>::populateFTable(table);
}
};
template <typename T>
struct TablePopulator<T, 0>
{
static void populateFTable(ftype* table)
{
table[0] = foo<T,0>;
}
};
template<typename T, unsigned max_N>
std::array<ftype, max_N>& initTable()
{
static std::array<ftype, max_N> table;
TablePopulator<T, max_N-1>::populateFTable(table.data());
return table;
}
template<typename T, unsigned max_N>
void foo_dynamic(unsigned actualN)
{
static auto ftable = initTable<T, max_N>();
if(actualN >= max_N)
throw std::runtime_error("Max param exceeded");
ftable[actualN]();
}
int main()
{
foo_dynamic<int, 10>(1);
foo_dynamic<int, 10>(5);
return 0;
}
EDIT: Given the constraints in the question edit, here's an approach where valid indices are specified manually, which uses an unordered_map instead of an array:
using ftype = void (*)();
template <typename T, unsigned N> void foo()
{
std::cout << N << std::endl;
}
template<typename T, size_t ... Indices>
void foo_dynamic_indices(size_t actual_index)
{
static std::unordered_map<size_t, ftype> fmap = {{Indices, foo<T,Indices>}...};
auto fIt = fmap.find(actual_index);
if(fIt == fmap.end())
throw std::runtime_error("Index not found");
fIt->second();
}
int main()
{
foo_dynamic_indices<int, 0, 3, 400, 1021, 10000000>(10000000);
foo_dynamic_indices<int, 0, 3, 400, 1021, 10000000>(4); //Exception
return 0;
}

Associating an array with a variadic template

I'm now learning a little about templates and templates in C++11, C++14 and C++1z. I'm trying to write a variadic class template with an inside class that will associate an int to every template argument - and have a constexpr method that returns its array representation.
Let's say that I have ensured that the template cannot receive two of the same type as an argument. I was thinking about doing it somewhat like this:
template <typename... Types>
struct MyVariadicTemplate {
//we know that all types in Types... are different
template <int... Values>
struct MyInnerTemplate {
//I need to make sure that sizeof...(Values) == sizeof...(Types)
constexpr std::array<int, sizeof...(Values)> to_array() {
std::array<int, sizeof...(Values)> result = {Values...};
return result;
// this is only valid since C++14, as far as I know
}
};
};
this code should be valid (if it's not, I'd love to know why). Now, I'd like to add another inner template:
template <typedef Type>
struct AnotherInnerTemplate {};
that has a public typedef, which represents MyInnerTemplate with one on the position of Type in Types... and zeros elsewhere - and here I'm lost. I don't know how to proceed
I would appreciate any hint on how that can be done - and if I'm heading towards the wrong direction, I hope somebody can give me a hint on how to do that.
I think what you're looking for is something like this.
#include <array>
#include <cstddef>
#include <iostream>
#include <type_traits>
template <typename NeedleT, typename... HaystackTs>
constexpr auto get_type_index_mask() noexcept
{
constexpr auto N = sizeof...(HaystackTs);
return std::array<bool, N> {
(std::is_same<NeedleT, HaystackTs>::value)...
};
}
template <typename T, std::size_t N>
constexpr std::size_t ffs(const std::array<T, N>& array) noexcept
{
for (auto i = std::size_t {}; i < N; ++i)
{
if (array[i])
return i;
}
return N;
}
int
main()
{
const auto mask = get_type_index_mask<float, bool, int, float, double, char>();
for (const auto& bit : mask)
std::cout << bit;
std::cout << "\n";
std::cout << "float has index " << ffs(mask) << "\n";
}
Output:
00100
float has index 2
The magic happens in the parameter pack expansion
(std::is_same<NeedleT, HaystackTs>::value)...
where you test each type in HaystackTs against NeedleT. You might want to apply std::decay to either type if you want to consider, say, const int and int the same type.
template <int size, int... Values> struct AnotherImpl {
using Type = typename AnotherImpl<size - 1, Values..., 0>::Type;
};
template <int... Values> struct AnotherImpl<0, Values...> {
using Type = Inner<Values...>;
};
template <class T> struct Another {
using Type = typename AnotherImpl<sizeof...(Types) - 1, 1>::Type;
};
Full:
template <class... Types> struct My {
template <int... Values> struct Inner {
constexpr std::array<int, sizeof...(Values)> to_array() {
return std::array<int, sizeof...(Values)>{Values...};
}
};
template <int size, int... Values> struct AnotherImpl {
using Type = typename AnotherImpl<size - 1, Values..., 0>::Type;
};
template <int... Values> struct AnotherImpl<0, Values...> {
using Type = Inner<Values...>;
};
template <class T> struct Another {
using Type = typename AnotherImpl<sizeof...(Types) - 1, 1>::Type;
};
};
auto main() -> int {
My<int, float, char>::Another<int>::Type s;
auto a = s.to_array();
for (auto e : a) {
cout << e << " ";
}
cout << endl;
return 0;
}
prints:
1 0 0
Is this what you want?

Template non-type templated reference parameter

I have a series of templated classes that I'd like to make aware of each other at compile-time. Each object may have other compile-time attributes that would be used to setup runtime conditions for the code.
My ideal pattern would be something like this:
template <unsigned int A, unsigned int B>
class FirstClass
{
};
template < template<unsigned int A, unsigned int B> FirstClass &firstClass >
class SecondClass
{
};
//...
FirstClass<1,2> fc;
SecondClass<fc> sc;
ThirdClass<sc> tc;
//...
Is there a way to do this?
I can get close if I do something like this for SecondClass:
template < unsigned int A, unsigned int B, FirstClass<A,B> &firstClass >
But this then requires me to pass the two extra arguments (rather than have the compiler infer them) and will not scale very well.
Thanks!
The right question is: do you really care if the argument of the second template is really from the first, or is it ok with you if it behaves exactly like the first template?
In the second case, there is really nothing to do. Simply use normal template argument.
In the first case, you can always use static_assert with is_same. It would require the first type to have constants for the two arguments:
template <unsigned int A, unsigned int B>
class FirstClass
{
public:
constexpr static unsigned int a = A;
constexpr static unsigned int b = B;
};
Then you can do:
template <typename FC>
class SecondClass
{
static_assert(std::is_same<FC,FirstClass<FC::a, FC::b> >::value, "Wrong template argument for SecondClass");
};
If you are not using C++11, look at the static_assert implementation in Boost, it is not that complex. And you will also have to implement yourself the is_same, but I don't know that is difficult.
And to use it:
FirstClass<1,2> fc;
SecondClass<decltype(fc)> sc;
Note that you will never be allowed to use a local variable at template argument.
Another thing you might want to look at (still C++11) is a helper function:
If you re-write your second class as:
template <unsigned int A, unsigned int B>
struct SecondClass
{
FirstClass<A,B> fc;
A(FirstClass<A,B> arg)
:fc(arg)
{ }
};
Then you can write:
template <unsigned int A, unsigned int B>
SecondClass<A,B> secondClass(FirstClass<A,B> arg)
{
return SecondClass<A,B>(arg);
}
And in you function:
FirstClass<1,2> fc;
auto sc = secondClass(fc)
I think C++11's decltype is what you're looking for. It will let you abstain from writing those template arguments over and over again.
It's important to note that in the example below, the pointer code in SecondClass is entirely unnecessary and I only included it because I wasn't sure whether your project needed runtime access. ThirdClass is the preferred example.
EDIT: I read your comment about arbitrary number of types. FourthClass or FifthClass here may be what you're looking for. It uses variadic templates, tuples, and some TMP code (for_each iterating over a tuple) from https://stackoverflow.com/users/680359/emsr in question iterate over tuple.
I hope there is enough here to get you started.
#include<iostream>
#include<tuple>
#include<string>
template <unsigned int A, unsigned int B>
struct FirstClass
{
static constexpr unsigned int C = A;
static constexpr unsigned int D = B;
};
template < typename T, const T* const t >
struct SecondClass
{
static constexpr unsigned int FOR_THIRD_CLASS = T::C;
//SecondClass knows about a FirstClass instance at compile time
static constexpr T* const pFirstClass = t;
//uses FirstClass values, which were computed at compile time, at runtime
void printFirstClassValues() const {
//ThirdClass below is an example without pointers or references, which it sounds like you don't need
std::cout << t -> C << " " << t -> D;
}
};
template < typename T >
struct ThirdClass
{
void printSecondClassValue() const {
std::cout << "\nIn ThirdClass method: " << T::FOR_THIRD_CLASS;
}
};
static constexpr FirstClass<1,2> fc;
template<std::size_t I = 0, typename FuncT, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type
for_each(std::tuple<Tp...> &, FuncT) // Unused arguments are given no names.
{ }
template<std::size_t I = 0, typename FuncT, typename... Tp>
inline typename std::enable_if<I < sizeof...(Tp), void>::type
for_each(std::tuple<Tp...>& t, FuncT f)
{
f(std::get<I>(t));
for_each<I + 1, FuncT, Tp...>(t, f);
}
struct Functor
{
template<typename T>
void operator()(T& t) const { std::cout << t << ", "; }
};
template< typename... Ts >
struct FourthClass{
std::tuple< Ts... > myTuple;
//if you need it...
static constexpr int numberOfTypes = sizeof...(Ts);
FourthClass(Ts... pack):myTuple(pack...){
}
void print(){
for_each( myTuple, Functor() );
}
};
//maybe this is better - give it a tuple to begin with
template < typename my_tuple >
class FifthClass{
};
//just use your imagination here - these are ridiculous typedefs that don't ever make sense to use, I'm just showing you how to use FifthClass with a variable number of types
typedef SecondClass< decltype(fc), &fc > SC;
typedef ThirdClass<SC> TC;
typedef FourthClass<TC> FC;
typedef std::tuple<SC,TC,FC> ArbitraryClasses;
typedef std::tuple<SC,TC,FC,ArbitraryClasses> OtherArbitraryClasses;
typedef std::tuple<SC,TC,FC,ArbitraryClasses,OtherArbitraryClasses, int, std::string> MoreArbitraryClasses;
int main(){
SecondClass<decltype(fc), &fc> sc;
ThirdClass<decltype(sc)> tc;
sc.printFirstClassValues();
tc.printSecondClassValue();
std::cout << "\nEdit: here's a variadic example..." << std::endl;
FourthClass < int,unsigned int, short, const char*, int*, std::string > fourth(9,6,19,"this is a string", (int*)0xDEADBEEF, "I could keep going with any cout-able types");
fourth.print();
FifthClass < MoreArbitraryClasses > fifth;
return 0;
}

Can a template parameter itself be templatized?

Say I have the following code:
#include <iostream>
#include <functional>
template <int func(int)>
struct S : std::unary_function<int, int>
{
int operator()(int x) const
{
return func(x);
}
};
int foo(int x)
{
return x;
}
int main()
{
S<foo> s;
std::cout << s(42) << std::endl;
}
This works okay as a way of wrapping up a function inside of a functor, which means it can be used in other templated functions (like sort, for example (assuming the functor had the right signature)). I don't want to create a functor struct for every possible return/argument type (and realistically I can't), and so I tried the following:
template <template <typename R, // Make the return type and argument type template parameters!
typename A> R func(A)>
struct S : std::unary_function<R, A>
{
R operator()(A arg) const
{
return func(arg);
}
};
That didn't work; it gave me compilation errors. So then I tried:
template <typename R, typename A, R func(A)>
struct S : std::unary_function<R, A>
{
R operator()(A arg) const
{
return func(arg);
}
};
Which did work. Unfortunately though, I had to change instantiations of S to be S<int, int, foo> s; instead of the nicer S<foo> s;.
Is it at all possible to templatize the function passed as a template argument such that I can do S<foo> s; and not hard code the return type and argument type of the function in S?
My google-foo hasn't been able to find a specific answer.
Edit: Now I'm wondering if this isn't possible. I just thought of "what if foo is an overloaded function?" There wouldn't be, as far as I know, a way to know which foo to use when saying S<foo> s; and thus explicitly stating return/argument type is necessary. Is this correct thinking, and does this mean that the answer to my first question is "No, it's not possible"?
Unfortunately, I think it's the only way to prevent necessary conversions for passing functions.
But you can add function templates to help you deduce the types of (1) function args (2) function returns, like codes below:
template < typename R, typename A >
R result_of( R(A) );
template < typename R, typename A >
A arg0_of( R(A) );
Then you can use them to construct wanted function objects and let compilers do possible optimizations:
#define get_call( f ) call_t< decltype(result_of(f)), \
decltype(arg0_of(f)), f >()
// same as the class 'S'
template < typename R, typename A,
R unary( A ) >
struct call_t : std::unary_function<A,R> {
R operator()( A arg ) const {
return unary( arg );
}
};
Use the utility:
int neg( int arg ) {
return -arg;
}
auto s = get_call( neg );
cout << s( 1 ) << endl; // outputs: -1
It works too on function templates. Of course, you have to pass argument(s) to the template:
template < typename T >
T square( T arg ) {
return arg * arg;
}
template <>
int square( int arg ) {
cout << "square<int>()" << endl;
return arg * arg;
}
auto sq = get_call( square<int> );
cout << sq( 12 ) << endl; // outputs: square<int>()
// 144
Edit: for overloaded functions, you can do conversions to tell compilers which version you wanna invoke:
int cube( int arg ) {
return arg * arg * arg;
}
float cube( float arg ) {
return arg * arg * arg;
}
typedef float (*chosen)( float );
auto cu = get_call( (chosen)cube );
cout << showpoint << cu( 4 ) << endl; // outputs: 64.0000
You seem to want to have a non-type template template parameter. However, the only legal syntax for template template parameters is template < template-parameters > class. ("A template-argument for a template template-parameter shall be the name of a class template or an alias template, expressed as id-expression." § 14.3.3)
You could create a templated class whose constructor argument was a function pointer, but I'm guessing that you're worried that will create an indirect function call.
That is not possible. It is the same problem in principle as the following one: you wish to write just A<100> where A is defined as:
template<T N>
struct A {};
Given N is 100, T turns out to be int. Fine. That is deducible by human mind, but not by the compilers even if they be 100% conformant to the C++11 Standard. I've exactly the same problem here:
Pretty-print types and class template along with all its template arguments
--
So the alternative solution I think is this:
template <typename R, typename A>
struct S : std::unary_function<R, A>
{
typedef R (*Fun)(A);
Fun func;
S(Fun f) : func(f) {}
R operator()(A arg) const
{
return func(arg);
}
};
And then define MakeS function as:
template<typename R, typename A>
S<R,A> MakeS(R (*fun)(A))
{
return S<R,A>(fun);
}
Which you can use it as:
auto s = MakeS(foo);
Or, simply this:
S<int,int> s(foo);
The downside with this alternative is that the function foo doesn't have any chance to be inlined now.
Does this work for you?
It may not be as nice as S<foo> but keeps the arguments as 1 at the point of instantiation.
int f(int) { return 0; }
template<class R, class A> struct S
{
typedef R(*FTYPE)(A);
typedef R RET;
typedef A ARG;
};
template<class R, class A> S<R, A> FW(R(f)(A));
template<class T> struct F : std::unary_function<typename T::RET, typename T::ARG>
{
};
int main()
{
F<decltype(FW(f))> o;
}