I have the code below, that basically maps an std::integer_sequence<> into an std::array<> at compile time:
#include <iostream>
#include <utility>
#include <array>
template<int...Is>
constexpr auto make_array(const std::integer_sequence<int, Is...>& param) // this works */
// constexpr auto make_array(std::integer_sequence<int, Is...> param) // doesn't compile
{
    return std::array<int, sizeof...(Is)> {Is...};
}
int main()
{
    constexpr std::integer_sequence<int, 1,2,3,4> iseq;
    // If I pass by value, error: the value of 'iseq' is not usable in a constant expression
    constexpr auto arr = make_array(iseq);  
    for(auto elem: arr)
        std::cout << elem << " ";
}
The code works fine whenever make_array takes its argument by const-reference. Whenever I try passing it by value, like in the commented line, it spits an error:
error: the value of 'iseq' is not usable in a constant expression
constexpr auto arr = make_array(iseq);
Why is this? The parameter iseq is certainly a constant expression, why cannot I pass it to make_array?
For example, the code below works as expected when passing by value:
#include <iostream>
#include <utility>
struct Foo
{
    int _m;
    constexpr Foo(int m): _m(m){};
};
constexpr Foo factory_foo(int m)
{
    return Foo{m};
}
constexpr Foo copy_foo(Foo foo)
{
    return foo;
}
int main()
{
    constexpr Foo cxfoo = factory_foo(42);
    constexpr Foo cpfoo = copy_foo(cxfoo);
}
EDIT
I'm using g++5.1 from macports. Using clang++ 3.5, I get an error message even for the code that compiles with g++ (with const reference):
error: default initialization of an object of const type 'const std::integer_sequence' requires a user-provided default constructor
so I guess there is some issue with the lack of a user-provided default constructor, but at this point I don't really understand what's going on.
If a program calls for the default initialization of an object of a const-qualified type
T,Tshall be a class type with a user-provided default constructor.
However, integer_sequence does not have any user-provided constructors, and constexpr implies const for variables, so you can't define a constexpr object of that type without an initializer.
Adding an initializer makes it compile on Clang.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With