3

The following main.cpp illustrates the problem:

#include <type_traits>

template <class T, std::size_t N>
struct Array
{
    T data_[N];
};

template <const std::size_t* EltArray, std::size_t EltCount>
struct Foo
{

};

int main()
{
    // SIDE NOTE if arr is not declared static: the address of 'arr' is not a valid template argument
    // because it does not have static storage duration
    static constexpr std::size_t arr[3] = {1, 2, 3};
    Foo<arr, 3> foo;// WORKING

    static constexpr Array<std::size_t, 3> arr2 = {1, 2, 3};
    static constexpr const std::size_t* arr2_ptr = arr2.data_;
    Foo<arr2_ptr, 3> foo2;// ERROR:
    // 'arr2_ptr' is not a valid template argument of type 'const size_t*'
    // {aka 'const long long unsigned int*'} because
    // 'arr2.Array<long long unsigned int, 3>::data_' is not a variable

    static constexpr const std::size_t* test = std::integral_constant<const std::size_t*, arr2_ptr>{};// ERROR:
    // 'arr2_ptr' is not a valid template argument of type 'const long long unsigned int*' because
    // 'arr2.Array<long long unsigned int, 3>::data_' is not a variable

    return 0;
}

I don't understand why arr2.data_ is not reusable just like arr. Can someone explain ?

I'm using gcc: mingw-w64\x86_64-8.1.0-posix-sjlj-rt_v6-rev0

g++.exe -Wall -std=c++2a -fconcepts -O2

2
  • I didn't see anything blocking from eel.is/c++draft/temp.arg.nontype, but as all clang/gcc/msvc reject it Demo, I should miss something. Commented May 11, 2020 at 13:03
  • arr2_ptr compiles but the error talks about arr2::data_ so it seems that gcc is lazy. I get the same error with std::array Commented May 11, 2020 at 13:10

1 Answer 1

0

I want to share the answer i just found in open-std and a compliant solution.

We all know that we cannot pass any variable as non type.

Did you know that we can pass a const reference to anything we want ?!

So the solution is:

#include <array>

// When passing std::array<std::size_t, EltCount> (by value), i get the error:
// 'struct std::array<long long unsigned int, EltCount>' is not a valid type for a template non-type parameter

template <std::size_t EltCount, const std::array<std::size_t, EltCount>& Elts>
struct Foo {};

static constexpr std::array<std::size_t, 3> arr = {1, 2, 3};

int main()
{
    Foo<3, arr> foo;// WORKING

    return 0;
}

And the answer to the initial question is:

quote of the N4296

14.3.2 Template non-type arguments [temp.arg.nontype]

For a non-type template-parameter of reference or pointer type, the value of the constant expression shall not refer to (or for a pointer type, shall not be the address of): (1.1) — a subobject (1.8),

Moral of the story: we can do what we want with references, not with pointers.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.