0

Simple example first, doesn't compile with GCC12:

#include <array>
#include <iostream>
#include <initializer_list>

template <int nvars> class Test1 {

    public:
        Test1( std::initializer_list<int> IL ) : arr { 0 }
        {
            // See https://stackoverflow.com/questions/38932089/can-i-initialize-an-array-using-the-stdinitializer-list-instead-of-brace-enclo
        };

        const std::array<int,nvars> arr;
};

// CTAD guide                           / simple-template-id
Test1(std::initializer_list<int> IL) -> Test1<IL.size()>;

int main() {
    Test1 test1({1,2,3,4});
    std::cout << "nvars: " << test1.arr.size() << std::endl;
}

The simple-template_id here is Test1<IL.size()>, where IL.size() is a constexpr function returning 4. It does compile with a hardcoded 4, but that obviously defeats the purpose.

What is and is not allowed in the simple-template_id of the CTAD guide? Which names, which types of expressions?

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • 1
    Parameter like `IL` are never constexpr. So you can't use `IL.size()` as a template argument. – Jason Nov 14 '22 at 14:42
  • @JasonLiam: I already knew that; that's why I linked a failing compile. But your comment doesn't answer the question. – MSalters Nov 14 '22 at 14:45
  • *"What is and is not allowed in the simple-template_id of the CTAD guide?"* Same as in any other `simple-template_id`. Template arguments must be compile time constant. It doesn't matter if you're using them in CTAD guide or anywhere else. – Jason Nov 14 '22 at 14:46
  • As an aside, if you want something *deducible* from `{ ... }` whose size is part of the type and usable, you can simply define a deduction guide from array rvalues https://godbolt.org/z/b5eTPY1G8 – StoryTeller - Unslander Monica Nov 14 '22 at 14:46
  • @StoryTeller-UnslanderMonica: True - that's deducing an array type, and then using the array type (indirectly) in the simple-template-id part. – MSalters Nov 14 '22 at 14:52
  • It can be a bit less uncsontrainted if one desires https://godbolt.org/z/noxcfEeeE – StoryTeller - Unslander Monica Nov 14 '22 at 14:56
  • Just look at the deduction guide for std::array. – n. m. could be an AI Nov 14 '22 at 16:34

1 Answers1

0

The problem is that parameters like IL are not constexpr. This means that we can't use IL.size() as a template argument since template arguments are required to be compile time constant.

Thus to solve this we have to pass a compile time constant as a template argument. One way of doing this would be to make the parameter as a reference to an array of size N with elements of type T where both T and N are template parameters.

template<typename T, std::size_t N> Test1(T const(&&)[N]) -> Test1<N>;

Jason
  • 36,170
  • 5
  • 26
  • 60