1

Is it possible to parameterize non-type template arguments? I'm trying to generate a thunk that forwards its arguments to one of two compile time constant functions based on some runtime check, to get something hopefully along the lines of this:

#include <stdlib.h> int a(int, int, char) { return 0; } int b(int, int, char) { return 0; } // This doesn't work template<typename ReturnType, typename... Params> template<ReturnType (*first)(Params...), ReturnType (*second)(Params...)> ReturnType coin_flip(Params... params) { if (rand() % 2) { return first(params...); } else { return second(params...); } } int main() { return coin_flip<a, b>(1, 2, '3'); } 
1
  • Yes, but not deduce said parameters. There are proposals for C++1y/1z. I cannot recall if they got into 1y. Commented Apr 6, 2014 at 9:39

3 Answers 3

2

There is a workaround which uses type template parameters (via std::integral_constant) and macros:

#include <type_traits> template <typename, typename> struct coin_flip; template < typename ReturnType, typename... Params, ReturnType (*first)(Params...), ReturnType (*second)(Params...) > struct coin_flip < std::integral_constant<ReturnType (*)(Params...), first>, std::integral_constant<ReturnType (*)(Params...), second> > { static ReturnType call(Params&&... params) { if (rand() % 2) { return first(std::forward<Params>(params)...); } else { return second(std::forward<Params>(params)...); } } }; #define FUNCTION_CONSTANT(f) std::integral_constant<decltype(&f), f> #define COIN_FLIP(first, second, ...) \ coin_flip<FUNCTION_CONSTANT(first), FUNCTION_CONSTANT(second)>::call(__VA_ARGS__) 

Example of using:

std::cout << COIN_FLIP(a, b, 1, 2, '3') << std::endl; 
Sign up to request clarification or add additional context in comments.

Comments

0

Following may help:

template<typename F, F f1, F f2, typename... Params> auto coin_flip(Params&&... params) -> decltype(f1(std::forward<Params>(params)...)) { if (rand() % 2) { return f1(std::forward<Params>(params)...); } else { return f2(std::forward<Params>(params)...); } } int main() { return coin_flip<decltype(&a), &a, &b>(1, 2, '3'); } 

Comments

0

You might pass the functions as arguments to coin_flip (not as template parameters):

#include <iostream> #include <cstdlib> #include <type_traits> int a(int, int, char) { std::cout << 'a'; return 0; } int b(int, int, char) { std::cout << 'b'; return 0; } template<typename FnA, typename FnB, typename... Params> typename std::result_of<FnA&(Params...)>::type coin_flip(FnA a, FnB b, Params... params) { // For testing, the condition is removed here a(params...); return b(params...); } int main() { coin_flip(a, b, 1, 2, '3'); std::cout << '\n'; return 0; } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.