I'd like to write something like that :
template<int i> void f() {}
for (constexpr int i : {1,2,3})
{
f<i>();
}
Is it possible to iterate on constexpr ?
Thank you
As you probably understand, you cannot do the like of:
for (constexpr int i : {1,2,3})
{
f<i>();
}
because, if i is to vary from 1 through 3 in a loop, then it is a variable and
not a compiletime constant. And a variable cannot be a template argument,
as in f<i>: only a compiletime constant can be a template argument.
In C++11 and later, thanks to variadic templates,
you can effectively iterate over an arbitary sequence of compiletime constants
by using compiletime recursion of a template function that accepts a suitable arbitrary sequence
of template arguments.
That will hardly mean anything to you if you don't already know how to do it.
Here is a C++11 example that does what you want to express:
#include <type_traits>
#include <iostream>
template<int i> void f()
{
std::cout << i << '\n';
}
// This overload is chosen when there is only 1 template argument.
template<int First, int ...Rest>
typename std::enable_if<sizeof...(Rest) == 0>::type
for_each_f()
{
f<First>();
}
// This overload is chosen when there is > 1 template argument.
template<int First, int ...Rest>
typename std::enable_if<sizeof...(Rest) != 0>::type
for_each_f()
{
f<First>();
for_each_f<Rest...>();
}
int main()
{
for_each_f<2,3,5,7,11>();
return 0;
}
See it live
Besides variadic templates, this technique depends on the very important C++ meta-programming
principle of SFINAE, and on std::enable_if,
which is the tool that the Standard C++ library provides for exploiting SFINAE.
101010's answer demonstrates a more sophisticated and powerful style of
solution that is available in C++14 (and easy enough to implement in C++11
if you write some supporting boilerplate).
No you can't use a for loop to iterate over at compile time. The for control structure in C++ is used for runtime control flow.
However, you could use other compile time facilities. For example in C++ 14 you could achieve what you want in the following manner:
Define a template wrapper class that's gonna call your function.
template<int i>
struct wrapper {
void operator()() const { f<i>(); }
};
Use std::index_sequence to generate compile time indices.
template<template<int> class W, std::size_t... I>
void caller_impl(std::index_sequence<I...>) {
int t[] = { 0, ((void)W<I>()(), 1)... };
(void) t;
}
template<template<int> class W, std::size_t N, typename Indices = std::make_index_sequence<N>>
void call_times() {
caller_impl<W>(Indices());
}
Then call as
int main() {
call_times<wrapper, 42>();
}
Live Demo
If C++14 is not an option you could take a look here of how you could implement std::index_sequence your self.
Related
I am trying to construct a function tune that takes a templated function via std::function and initializes a series of that function based on a std::integer_sequence. I am not sure whether this is possible, and I am stuck. I made a working example that shows what I aim to achieve: a generic function that takes another function and an integer list as an argument. I would like to be able to use the syntax that is in the two lines commented out in the bottom, because with the working code, I have to make a tune function for each function.
#include <iostream>
#include <functional>
template<int I> void print_value() { std::cout << I << std::endl; }
template<int I> void print_value_squared() { std::cout << I*I << std::endl; }
template<int... Is>
void tune_print_value(std::integer_sequence<int, Is...>)
{
(print_value<Is>(), ...);
}
/* NOT SURE HOW TO DO THIS...
template<class Func&&, int... Is>
void tune(std::function<Func> f, std::integer_sequence<int, Is...)
{
(f<Is>(), ...);
}
*/
int main()
{
std::integer_sequence<int, 1, 2, 3> is;
tune_print_value(is);
// I would like:
// tune(print_value, is);
// tune(print_value_squared, is);
return 0;
}
This is not possible with a simple function pointer or std::function (as it can only point to one instance of a particular template!) but what you can do though is to wrap each function print_value or print_value_squared in a corresponding struct
struct print_value {
template <int I>
static constexpr int impl() {
std::cout << I << std::endl;
return I;
}
};
This struct then holds the templated implementation as a static member function with a predefined name such as impl (sadly you can't use operator () like for a functor as it is not allowed to be static)
Your tune function then takes this struct as a template argument and "magically" (in C++20 you could create a concept for this as follows, prior to it you might use SFINAE and std::enable_if as follows) accesses the wrapped template function impl.
template<class Func, int... Is>
auto tune(std::integer_sequence<int, Is...>) {
return (Func::template impl<Is>(), ...);
}
You will need the keyword template as a qualifier in this case to tell the compiler that the member function is a template.
You can then call the tunefunction like
tune<print_value>(is);
Try it here with a static member function impl or here with a non-static operator().
I have defined a typelist like this:
template <typename ... Types> struct typelist {};
using my_list = typelist<int, double, bool, float>;
Now I have a function template, e.g.
template<typename T>
void foo() {
std::cout << typeid(T).name() << std::endl;
}
and want to call this for every type in the typelist:
foo<int>();
foo<double>();
foo<bool>();
foo<float>();
I tried to find a recursive way to solve this, but I am having trouble to define the correct, probably nested, variadic templates for the required foo functions. Do you have any hints for a neat solution to this problem?
template<class... Types> auto foo_foreach(typelist<Types...>) {
return (foo<Types>(), ...);
}
int main() {
foo_foreach(my_list{});
}
For a real oldschool, well, use template recursion you've attempted before:
void foo_foreach(typelist<>) {}
template<class Head, class... Tail> void foo_foreach(typelist<Head, Tail...>);
template<class Head, class... Tail> void foo_foreach(typelist<Head, Tail...>) {
foo<Head>();
foo_foreach(typelist<Tail...>{});
}
Here is a c++20 answer only that uses lambda template.
template <typename... Ts, typename C>
constexpr void for_types(C&& c) {
(c.template operator()<Ts>(), ...);
}
for_types<int, float, char>([]<typename T>()
{
std::cout << typeid(T).name() << std::endl;
});
If you need this to work with C++14 then you can use the initializer_list trick to avoid a C++17 fold expression. This will hopefully be cheaper to compile than a recursive approach:
template<class... Ts> void foo_foreach(typelist<Ts...>) {
(void) std::initializer_list<int>{(foo<Ts>(), 0)...};
}
int main() {
foo_foreach(my_list{});
}
Godbolt example: https://godbolt.org/z/o91Th466s
There is a good explanation of the initializer_list trick at https://blog.tartanllama.xyz/exploding-tuples-fold-expressions/
From that article:
[...] parameter packs can only be expanded in contexts which expect a syntactic list, such as initializers and function call arguments. You can’t just expand them bare in a function body. In C++17, this problem has a nice solution, but prior to that we need to use some pretty horrible hacks. [...] one possibility [...] uses std::initializer_list to create a context in which the parameter pack can be expanded.
The trick is the , 0 inside the initializer_list initializer, which evaluates the function call, and uses 0 as the initializer value.
This question was inspired by this answer. I wonder what are/were the best ways to simplify it in given standards. One I know and personally used/still use since C++14 is macro REQUIRES(x):
With definition:
template<long N>
struct requires_enum
{
enum class type
{
none,
all
};
};
#define REQUIRES(...) requires_enum<__LINE__>::type = \
requires_enum<__LINE__>::type::none, \
bool PrivateBool = true, \
typename std::enable_if<PrivateBool && (__VA_ARGS__), int>::type = 0
And use if even for non-templated function calls:
template<REQUIRES(sizeof(int)==4)>
int fun() {return 0;}
int main()
{
fun(); //only if sizeof(int)==4
}
The original REQUIRES I use is from this post.
What are the other good techniques?
Some examples of SFINAE that require some, or long time to understand for reader that just started the adventure with SFINAE:
Pre-C++11 SFINAE example (Source):
template <typename T>
struct has_typedef_foobar {
// Types "yes" and "no" are guaranteed to have different sizes,
// specifically sizeof(yes) == 1 and sizeof(no) == 2.
typedef char yes[1];
typedef char no[2];
template <typename C>
static yes& test(typename C::foobar*);
template <typename>
static no& test(...);
// If the "sizeof" of the result of calling test<T>(nullptr) is equal to sizeof(yes),
// the first overload worked and T has a nested type named foobar.
static const bool value = sizeof(test<T>(nullptr)) == sizeof(yes);
};
If you are working with C++11 (the example code contains std::enable_if, so I guess this is the case) or a successive revision, I would use a static_assert in this case:
int fun() {
static_assert(sizeof(int)==4, "!");
return 0;
}
int main() {
fun();
}
You don't have a set of functions from which to pick a working one up.
As I've been said once, this is more a substitution failure is always an error than a substitution failure is not an error.
What you want is a compile-time trigger and a static_assert does it with gentle error messages.
Of course, it's also far easier to read than a complicated sfinae expression too!!
If you want to choose between two functions and you don't want to use template machinery or macros, do not forget that overloading is part of the language (pre-C++11 working example):
#include <iostream>
template<bool> struct tag {};
int fun(tag<true>) { return 0; }
int fun(tag<false>) { return 1; }
int fun() { return fun(tag<sizeof(int) == 4>()); }
int main() {
std::cout << fun() << std::endl;
}
This can be easily extended to the cases where the functions are more than two:
#include <iostream>
template<int> struct tag {};
int fun(tag<0>) { return 0; }
int fun(tag<1>) { return 1; }
int fun(tag<2>) { return 2; }
int fun(bool b) {
if(b) { return fun(tag<0>()); }
else { return fun(tag<(sizeof(int) == 4) ? 1 : 2>());
}
int main() {
std::cout << fun(false) << std::endl;
}
You can put those functions in an anonymous namespace and get away with them.
Of course, note also that in pre-C++11 we were authorized to write enable_if and all the other things from type_traits for ourselves.
As an example:
template<bool b, typename = void>
struct enable_if { };
template<typename T>
struct enable_if<true, T> { typedef T type; };
Enable if is pretty easy to implement. Take a look at this implementation:
template<bool b, typename T = void>
struct enable_if {
typedef T type;
};
template<typename T>
struct enable_if<false, T> {};
In C++11 I usually declare some aliases. Since you're stuck in pre C++11 era, you can do that instead:
template<bool b>
struct enable_if_parameter : enable_if<b, int*> {};
Then you can use the struct like this:
template<typename T, typename enable_if_parameter<(sizeof(T) >= 0)>::type = 0>
void someFunc() {
// ...
}
If you can allow yourself some C++17, you could do that:
template<bool b>
using enable_if_parameter = std::enable_if_t<b, int*>;
And then do that:
template<typename T, enable_if_parameter<std::is_same_v<T, int>> = 0>
I also love the void_t idom to create new type traits:
template<typename T, typename = void>
struct has_callme : std::false_type {};
template<typename T>
struct has_callme<T, void_t<decltype(std::declval<T>().callme())>> : std::true_type {};
In C++03 you simply write enable_if yourself. It requires no C++11 features.
The reason why you use different techniques is that the pre-C++11 compilers sometimes have a funny definition of what SFINAE and what should be an error. MSVC is the current major compiler who still (in the pre-C++17 era) has very quirky definition of what is valid SFINAE due to their "SFINAE decltype" issues.
In C++11 you should write void_t and enable_if_t to simplify your SFINAE stuff.
You should also write this:
namespace details {
template<template<class...>class Z, class always_void, class...Ts>
struct can_apply:std::false_type{};
template<template<class...>class Z, class...Ts>
struct can_apply<Z, void_t<Z<Ts...>>, Ts...>:std::true_type{};
}
template<template<class...>class Z, class...Ts>
using can_apply = details::can_apply<Z, void, Ts...>;
which lets you write traits and ask if something is valid easily (can you call a method? Create an alias that does a decltype on the invocation, then ask if you can apply the type to the alias). This is still needed in C++14 and 17, but C++20 probably will get is_detected which serves a similar purpose.
So can_print is:
template<class T>using print_result = decltype(
std::declval<std::ostream&>() << std::declval<T>()
);
template<class T>using can_print = can_apply< print_result, T >;
it is either truthy or falsy depending on if << works on a stream with it.
In C++14 you can start using hana-style metaprogramming to create lambdas that do type manipulation for you. In C++17 they become constexpr, which gets rid of some issues.
Using techniques like the OP's macro tends to lead to ill formed programs, no diagnostic required. This is because if a template has no valid template parameters that would lead to the body of the template being valid code, your program is ill formed, no diagnostic required.
So this:
template<REQUIRES(sizeof(int)==4)>
int fun() {
// code that is ill-formed if `int` does not have size 4
}
will most likely compile and run and "do what you want", but it is actually an ill-formed program when sizeof(int) is 8.
The same may be true of using this technique to disable methods on classes based on the template arguments of the class. The stanard is unclear on the issue, so I avoid it.
The REQUIRES macro tries to hide how it works behind magic, but it is far too easy to step over the line and generate an ill-formed program. Hiding the magic when the details of the magic cause your code to be ill-formed is not a good plan.
Tag dispatching can be used to simplify otherwise complex SFINAE issues. It can be used to order overloads or pick between them, or pass more than one bundle of types to a helper template function.
template<std::size_t N>
struct overload_priority : overload_priority<N-1> {};
template<>
struct overload_priority<0> {};
Now you can pass overload_priority<50>{} to a set of functions, and the one with the highest overload_priority<?> in that slot will be preferred.
template<class T>struct tag_t{using type=T;};
namespace details {
inline int fun( tag_t<int[4]> ) { return 0; }
inline int fun( tag_t<int[8]> ) { return 1; }
}
int fun() { return details::fun( tag_t<int[sizeof(int)]>{} ); }
just dispatched to a different function depending on the size of int.
Both fun overloads get compiled and checked, so you don't run into the stealth ill-formed program problem.
A function whose validity is not a function of its template arguments is not safe to use in C++. You must use a different tactic. Machinery that makes this easier to do just makes it easier to write ill-formed programs.
I want to write a class method that takes a template parameter pack, but zero arguments, and "iterate" over the types:
struct Bar {
template <typename T, typename... Ts>
void foo() {
// something with T that involves Bar's members
foo<Ts...>();
}
};
What is the preferred way to implement this?
You may use the following:
struct Bar {
template <typename... Ts>
void foo() {
int dummy[] = {0 /*Manage case where Ts is empty*/,
(bar<Ts>(), void() /* To avoid overload `operator,` */, 0)...};
(void) dummy; // suppress warning for unused variable.
}
template <typename T>
void bar()
{
// something with T that involves Bar's members
}
};
In C++17, it can be simplified with Folding expression:
struct Bar {
template <typename... Ts>
void foo() {
(static_cast<void>(bar<Ts>()), ...);
}
template <typename T>
void bar()
{
// something with T that involves Bar's members
}
};
template<class...Fs>
void do_in_order(Fs&&...fs) {
int _[]={0, ( std::forward<Fs>(fs)(), void(), 0 )...};
(void)_;
}
hides the syntax required to execute a pack of function objects in left to right order.
Then:
struct Bar {
template <class... Ts>
void foo() {
do_in_order([&]{
using T = Ts;
// code
}...);
}
};
and in a conforming compiler, we will run the // code with T being each type from left to right.
Note that some compilers claiming to be C++11 compilers may fail to compile the above.
The advantage of this technique is that it hides the nasty "expand and evaluate templates" code within a function with a clear name. You write do_in_order once, and it usually suffices for almost every use of that array-expansion trick.
There are a two important reasons to use this kind of esoteric syntax instead of the "more simple" recursive solutions.
First, it makes things easier for the optimizer. Optimizers sometimes give up after a pile of recursive calls.
Second, the sum of the lengths names of the function signatures for the traditional recursive functions grow at O(n^2). If you use helper types, the total length of the names is also O(n^2). Unless you are careful, this can cause compile time, link time, and binary size bloat.
In C++1z there are plans for some "fold" syntax that may make the esoteric parts of the above less esoteric.
I like overloaded functions and using a typelist:
#include <iostream>
#include <typeinfo>
template <typename ...Ts> struct typelist { };
void foo_impl(typelist<> )
{
// we are finished
}
template <typename T, typename ...Ts>
void foo_impl(typelist<T, Ts...> )
{
std::cout << typeid(T).name() << ", ";
foo_impl(typelist<Ts...>{});
}
template <typename ...Ts>
void foo()
{
std::cout << "called with <";
foo_impl(typelist<Ts...>{});
std::cout << ">" << std::endl;
}
int main()
{
foo<int, char, float>();
}
Since the function template in the following code is a member of a class template, it can't be specialized without specializing the enclosing class.
But if the compiler's full optimizations are on (assume Visual Studio 2010), will the if-else-statement in the following code get optimized out? And if it does, wouldn't it mean that for all practical purposes this IS a function template specialization without any performance cost?
template<typename T>
struct Holder
{
T data;
template<int Number>
void saveReciprocalOf();
};
template<typename T>
template<int Number>
void Holder<T>::saveReciprocalOf()
{
//Will this if-else-statement get completely optimized out
if(Number == 0) data = (T)0;
else data = (T)1 / Number;
}
//-----------------------------------
void main()
{
Holder<float> holder;
holder.saveReciprocalOf<2>();
cout << holder.data << endl;
}
Chances are it will be optimized. But if you want to be sure you can use a compile-time if by using templates, e.g. Boost’s MPL if_ implementation.
Or you can use SFINAE (Boost.enable_if).
Usually the way to solve this kind of problem is through overloading
template<typename T>
struct Outer {
template<int I>
void inner() {
inner(int_<I>());
}
private:
template<int I>
struct int_ { };
void inner(int_<0>) {
// for I == 0
}
template<int I>
void inner(int_<I>) {
// for others...
}
};
This mimics explicit specializations quite well, and even works in cases where type check for the other paths would go mad (unlike the if solution)
// ...
template<int I>
void inner(int_<I>) {
int tmp[I];
}
// ...
That works because this path is only taken if I != 0. Now in your case, i first of all wonder why you don't just pass a normal function argument. You don't seem to need the compile time nature of I.
// works just fine too in your example
template<typename T>
void Holder<T>::saveReciprocalOf(int Number)
{
// Will this if-else-statement get completely optimized out
if(Number == 0) data = (T)0;
else data = (T)1 / Number;
}
This also has good chances of being optimized if the compiler inlines the function call. Using the template non-type parameter where it's not strictly necessary only limits the abilities of that function not to work with runtime values.
Thanks. Since I want to be certain the conditional is optimized out (because it needs to called very often deep inside loops and I use a switch-case outside the loops to pick the correct path), I'll probably end up using enable_if_c something like in the following code:
using boost::enable_if_c;
template<typename T>
struct Dummy
{
template<int N>
typename enable_if_c<N==2,bool>::type isPrimary() {return true;}
template<int N>
typename enable_if_c<N==3,bool>::type isPrimary() {return true;}
template<int N>
typename enable_if_c<N==5,bool>::type isPrimary() {return true;}
template<int N>
typename enable_if_c<N!=2&&N!=3&&N!=5,bool>::type isPrimary() {return false;}
};
To me this seems a bit less cluttered than the suggestion by Johannes. Although the last (default) case can get quite ugly.