I saw some valid template code as below:
template<typename R, typename P, size_t N, size_t... I>
constexpr array<R, N> to_array_impl(P (&a)[N], std::index_sequence<I...>) noexcept
{
return { {a[I]...} };
}
Well, what does the double brace mean here? When do we need to use double brace(I'm using c++17 now), I guess it's restricted to return statement?
I also see code like below, that there's function call inside double braces:
template<typename R, typename P, size_t N, size_t... I>
constexpr array<R, N> to_array_impl(P (&&a)[N], std::index_sequence<I...>) noexcept
{
return { {move(a[I])...} };
}
So what's the difference here between using one brace and two braces?
Thanks!
When do we need to use double brace(I'm using c++17 now), I guess it's restricted to return statement?
The double braces are not require in your given example. Just surrounding the pack expansion with one set of braces is enough.
So what's the difference here between using one brace and two braces?
In your given example, adding double braces have no additional effect. That is, using single set of braces is equivalent to using double braces(in the given example).
Related
I am wondering if it is possible to pass a integer parameter of a lambda to a nested template lambda as its template argument. If it is possible then it gives a lot of advantages to use template lambda.
For example, using a template lambda is an awkward work. Considering
auto foo=[]<int N>(){
return N;
};
std::cout<<foo.operator()<5>();
Here when we are calling lambda foo, we have to invoke its native operator() with template argument <5> and then call it by another ().
So, if we can design a lambda to pass a normal integer parameter and internally the lambda call its local template lambda and do the work, it then can save all this awkwardness. I designed this simple lambda to convert parameter N to its native template lambda's argument. But I am stuck on how to call this template lambda.
auto foo=[](int N){
auto f=[]<int N>(){
return N;
};
return f.operator()<N>(); //this cannot compile!
};
My question is how I can call this f within foo? Or is this idea entirely impossible because template argument requires N to be constexpr or compile-time-constant?
Thank you for cigien's lightening fast response! It seems
this idea entirely impossible because template argument requires N to be constexpr or compile-time-constant
And further to Chris suggestion of a possible workaround, I try to solve my original template-lambda-invoking-awkwardness by using an std::integral_constant. This is how far I can get:
#define constInt(N) integral_constant<int, N>{}
auto foo=[]<int N>(std::integral_constant<int, N>&& n){
auto f=[](){
return array<int, N>{};
};
return f();
};
auto ary1=foo(integral_constant<int, 5>{});
auto ary2=foo(constInt(5));
static_assert(is_same_v<decltype(ary1), array<int, 5>>);
static_assert(is_same_v<decltype(ary2), array<int, 5>>);
By using a macro constInt, it saves a little typing work. Then my question is:
Is this the best we can achieve with template lambda invoking? What if the template parameter is a type that we cannot take advantage of std::integral_constant?
With Davis's suggestion of using a tag, I am rephrasing my question as this concrete task below:
**creating a lambda to return a std::array<T,N>
Here is usual lambda:
auto createArray=[]<typename T, size_t N>(){
return array<T, N>{};
};
But calling it is an awkward way with template parameter:
auto ary4=createArray.operator()<string, 5>();
static_assert(is_same_v<decltype(ary4), array<string, 5>>);
Can we avoid using this .operator()<string, 5> by just using normal parameter like std::itegral_constant? For example, something like createArray(class_tag<string>{},integral_constant<size_t, 5>{});
Then how should we implement this class_tag?
It turns out this is a very easy task and here is my implementation demo:
template<typename T>
struct class_tag{};
auto createArray2=[]<typename T, size_t N>(class_tag<T>&&, integral_constant<size_t, N>&&){
return array<T, N>{};
};
auto ary5=createArray2(class_tag<string>{}, integral_constant<size_t, 5>{});
static_assert(is_same_v<decltype(ary5), array<string, 5>>);
So, I guess it solves my issue with help of all great comments below. Thank you for all!
template<auto x>
using constant_t = std::integral_constant<std::decay_t<decltype(x)>, x>;
template<auto x>
constexpr constant_t<x> constant{};
template<class T>
struct tag_t { using type=T; };
template<class T>
constexpr tag_t<T> tag{};
auto make_array=[]<auto N, class T>(constant_t<N>, tag_t<T>){
return std::array<T, N>{};
};
std::cout << make_array(constant<3>, tag<int>).size() << "\n";
Live example.
Here I use a tag dispatching technique. The tags carry the payload within their type, so can be passed by value and then the "payload" can be extracts as compile-time constants.
You can even make it a two-stage lambda if you want, where the template arguments are passed to an outer lambda, then the constants and types are used by an inner lambda:
auto make_array=[]<auto N, class T>(constant_t<N>, tag_t<T>) {
return [](auto&&...ts)requires (sizeof...(ts)==N && (std::is_convertible<decltype(ts), T>&&...))
{
return std::array<T,N>{ decltype(ts)(ts)... );
};
};
which is used like:
make_array(constant<3>, tag<int>)(1,2,3);
In older versions of C++, you can use auto arguments instead:
auto make_array=[](auto Size, auto Type) {
using T = typename decltype(Type)::type;
constexpr auto N = decltype(Size)::value;
return [](auto&&...ts)
{
return std::array<T,N>{ decltype(ts)(ts)... );
};
};
But constant<7> has to be replaced with
template<std::size_t N>
using ksize_t = std::integral_constant<std::size_t, N>;
template<std::size_t N>
constexpr ksize_t<N> ksize{};
because of the lack of auto non-type template parameters.
If you move template outside of lambda it will work very conveniently:
template<int N>
auto lambda = []{ return N; };
int main()
{
return lambda<5>();
}
https://gcc.godbolt.org/z/PsvYvW36Y
So, I actually have the answer: lambda parameter cannot be directly translated into template argument. Some trick of helper class is needed such as integral_constant, integer_sequence, class_tag etc. And because function parameter is not considered as compile-time constant, there is no way of directly using it as template argument. However, to solve my immediate requirement to avoid using lambda template argument call, it is workable by using these helper class. (see above comments and example code.)
Variadic templates are really useful for doing recursive operations. In this case I'd like each recursive call to operate on two arguments so I don't have to repeatedly call the same function. To achieve this I can write:
f() {}
template<typename M,
typename N,
typename... Rest>
f(M arg1, N arg2, Rest... rest)
{
doStuff(arg1, arg2);
f(rest);
}
Then I would call this as such:
f(arg1a, arg1b,
arg2a, arg2b,
arg3a, arg3b);
However, if the call is not formatted so nicely, and all the arguments are on one line, or the column is split at the wrong point, it becomes quite unreadable. Especially so if the call might contain a dozen or so pairs. I attempted to remedy this by requiring a parameter pack of pairs to be passed in. I would like the function to have to be called like this:
f({arg1a, arg1b},
{arg2a, arg2b},
{arg3a, arg3b});
This seems to be mostly failing as the initializer list does not get deduced to a pair. I can call make_pair on each set of arguments, but that just solves a readability problem with another readability problem. Is there any way to get this sort of calling syntax to work? The arguments are not the same across pairs or within pairs.
Sorry, it is not possible: an implicit type conversion from braced list to a user-defined type. And the only conversion that is possible is for std::initializer_list, but it can be only done for the same types, or for convertible types.
With this said, I would offer this, as a possibility,
template <typename M, typename N>
void doStuff(M&&, N&&) {}
template <typename M, typename N>
struct MyRepeater;
template <typename M, typename N>
MyRepeater<M, N> f(M&& one, N&& two);
template <typename M, typename N>
struct MyRepeater {
template <typename I, typename J>
MyRepeater<I, J> operator()(I&& one, J&& two) const {
return f(std::forward<I>(one), std::forward<J>(two));
}
};
template <typename M, typename N>
MyRepeater<M, N> f(M&& one, N&& two) {
doStuff(one, two);
return MyRepeater<M, N>();
}
int main() {
f(Foo1(), Foo2())(Bar1(), Bar2())(Bar2(), Foo1());
}
Of course, the downside is that only for readability you have two write some extra code (in my opinion, it is not a bad motivation).
It may seem surprising but the best solution I've found for this is actually a "blast from the past" that doesn't use variadics at all.
struct F {
template <class M, class N>
F& operator()(M arg1, N arg2) {
doStuff(arg1, arg2);
return *this;
}
};
F{} (arg1a, arg1b)
(arg2a, arg2b);
And so on. Although, I'll also note that clang-format does not format this nicely. So I ended up doing something slightly different again.
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.
I want to write a function which kind of iterates over a std::tuple<...>. The iteration itself won't produce any problems regarding the tuple's template types, because '...' have the same types (like int, int, int, ...). I implemented already a working function 'Foo' with a helper struct 'Helper' using template metapgrogramming – everything is fine.
But when I want to implement an alternative version, using a constexpr function 'helper', the compiler (g++ 5.2.0) gets stuck in an infinite loop of error messages. From what I can get from these messages, the 'position' template parameter is instantiated as ridicilously big (== 4294967245) instead of (== 1). I tried to get both versions as close in syntax and nomenclature as possible.
Minimal example
#include <tuple>
// template metaprogramming version
template
<class T, std::size_t position>
struct Helper{
static int
help(T tuple) {
return std::get<position>(tuple) +
Helper<T,position - 1>::help(tuple);
}
};
// template metaprogramming version, specialized
template
<class T>
struct Helper<T,0>{
static int
help(T tuple) {
return std::get<0>(tuple);
}
};
// function version, not working
template
<class T, std::size_t position>
constexpr int
helper(T tuple) {
return
0 == position ?
std::get<position>(tuple) + helper<T,position-1>(tuple) :
std::get<0>(tuple);
}
template
<class T>
auto
Foo(T tuple) {
constexpr std::size_t dimension = std::tuple_size<T>::value;
// working version, using the helper struct
return Helper<T,dimension - 1>::help(tuple);
// wrong(?) version, using the constexpr helper function
return helper<T,dimension - 1>(tuple);
}
int main() {
std::tuple<int,int> t(1,1);
Foo(t);
return 0;
}
My questions:
Is it principally wrong to try this kind of iteration during compile
time with constexpr functions?
If not, is it a bug in the compiler
or how should a correct version look like?
I am totally aware that, due to the same types in the tuple (int,int,...), one could implement a similar version with vectors. But I think that the tuple version is conceptually better to my kind of problem and faster during runtime.
When you have a function template - all the code must be compiled out. So here:
template
<class T, std::size_t position>
constexpr int helper(T tuple) {
return
0 == position ?
std::get<position>(tuple) + helper<T,position-1>(tuple) :
std::get<0>(tuple);
}
We always compile both parts of the conditional (side-note: your conditional is backwards). So when position == 0, both the std::get<0>(tuple) part is compiled and the std::get<0>(tuple) + helper<T, -1>(tuple) part is compiled. But then to do that, we'd need to compile helper<T, -2>(tuple). And helper<T, -3>(tuple). We recursive infinitely.
Your specialization approach works because Helper<T, 0> just does std::get<0>. There is no other logic in there, so we stop. If you want to do this functionally, an easier way would be to pass the position as an argument. That is:
template <std::size_t position>
using Pos = std::integral_constant<std::size_t, position>; // to save me some typing
template <typename T>
constexpr int helper(T const& tuple, Pos<0> )
{
return std::get<0>(tuple);
}
template <typename T, std::size_t position>
constexpr int helper(T const& tuple, Pos<position> )
{
return std::get<position>(tuple) + helper(tuple, Pos<position - 1>{});
}
Here, we do the conditional via overloading - so once we get to helper(T, Pos<0> ), we successfully terminate the recursion.
In C++1z, this becomes a ton easier with fold expressions, where you can just do:
template <typename T>
constexpr int sum_tuple(T const& tuple) {
return sum_tuple(tuple, std::make_index_sequence<std::tuple_size<T>::value>{});
}
template <typename T, std::size_t... Is>
constexpr int sum_tuple(T const& tuple, std::index_sequence<Is...> )
{
return (std::get<Is>(tuple) + ... );
}
So my questions: Is it principally wrong to try this kind of iteration during compile time with constexpr functions?
Yes, it's wrong, as you've done it. It can be done, but you can't terminate the compile-time recursion with a run-time condition.
When you instantiate helper<T, N>(T) that instantiates helper<T, N-1>(T) which instantiates herlper<T, N-2>(t) and so on, with nothing to terminate the recursion.
The class template version terminates when it reaches N==0 because of the partial specialization, but you can't partially specialize a function template.
Barry's solution works by using a second overload to terminate the recursion, so that when it reaches 0 it chooses a different function and doesn't keep instantiating the same one forever.
Let's say we have the following type
template <bool... Values>
struct foo{};
I want to create a variadic template from a constexpr array bool tab[N]. In other words, I want to do something like:
constexpr bool tab[3] = {true,false,true};
using ty1 = foo<tab[0], tab[1], tab[2]>;
But I want to do it programmatically. For now, I've tried the following:
template <std::size_t N, std::size_t... I>
auto
mk_foo_ty(const bool (&tab)[N], std::index_sequence<I...>)
{
// error: template argument for template type parameter must be a type
return foo<tab[I]...>{};
}
// error (see mk_foo_ty)
using ty2 = decltype(mk_ty(tab, std::make_index_sequence<3>{}));
// error: expected '(' for function-style cast or type construction
using ty3 = foo<(tab[std::make_index_sequence<3>])...>;
I'm not even sure if it's possible. Maybe resorting to something like Boost.Preprocessor, but I don't like the idea. So, does anyone have an idea? Thanks!
EDIT
I have on one side a framework of constexpr square matrices of booleans which can be created at compile-time using xor, negation, etc.
On the other side, I have a framework of templates which statically creates operations using informations encoded in variadic templates using boolean as parameters.
My goal is to bridge the gap between these two frameworks. Thus, I can't go with hardcoded solutions.
EDIT 2
I've found this question with the same problem and a nice answer, which is very close to the T.C.'s one (using a pointer). The extern linkage is also very important.
However, I realize I forgot a key element. My bool array is contained in a matrix structure to be able to overload operators ^, |, etc.:
template <std::size_t N>
struct matrix
{
const bool data_[N*N];
template<typename... Values>
constexpr matrix(Values... values) noexcept
: data_{static_cast<bool>(values)...}
{}
constexpr bool operator [](std::size_t index) const noexcept
{
return data_[index];
}
}
Thus, if we apply T.C's solution:
template<std::size_t N, const bool (&Tab)[N], class>
struct ty1_helper;
template<std::size_t N, const bool (&Tab)[N], std::size_t... Is>
struct ty1_helper<N, Tab, std::index_sequence<Is...>>
{
using type = foo<Tab[Is]...>;
};
template<std::size_t N, const bool (&Tab)[N]>
using ty1 = typename ty1_helper<N, Tab, std::make_index_sequence<N>>::type;
Compilers complain about passing a non-type parameter :
// error: non-type template argument does not refer to any declaration
// using t = make_output_template<m.data_, std::make_index_sequence<3>>;
// ^~~~~~~
using t = ty1<3, m.data_>;
The way I did it in the comments above, using a global constexpr variable with external linkage (necessary due to GCC's nonconforming external linkage requirement, see bug 52036), would probably blow up spectacularly at link time if you put it in a header and include the header in different translation units. A solution that's good for one translation unit only isn't much of a solution. One workaround is to store the matrix as a static data member of a class.
struct matrix_holder {
static constexpr matrix<2> mat = {true, false, true, false};
};
template<std::size_t N, const matrix<N> &Mat, class>
struct ty1_helper;
template<std::size_t N, const matrix<N> &Mat, std::size_t... Is>
struct ty1_helper<N, Mat, std::index_sequence<Is...>> {
using type = foo<Mat[Is]...>;
};
template<std::size_t N, const matrix<N> &Mat>
using ty1 = typename ty1_helper<N, Mat, std::make_index_sequence<N*N>>::type;
static_assert(std::is_same<ty1<2, matrix_holder::mat>,
foo<true, false, true, false>>::value, "Oops");
Demo. Also, since using matrix_holder::mat in ty1<2, matrix_holder::mat> counts as an odr-use, to be fully conforming you should supply a definition:
constexpr matrix<2> matrix_holder::mat;