vehsakul
vehsakul

Reputation: 1158

Constexpr value as nontype template parameter of pointer type

The following code

#include <iostream>
#include <initializer_list>

using namespace std;


constexpr initializer_list<int> list = {1, 2, 3};

template<const int* begin, const int* end>
bool contains(int v)
{
    if constexpr(begin != end)
    {
        if (*begin = v)
            return true;
        else
            return contains<next(begin), end>(v);
    }
    return false;
}


int main()
{
    cout << contains<list.begin(), list.end()>(2);
    return 0;
}

produces some really weird error message:

main.cpp: In function 'int main()':
main.cpp:25:49: error: no matching function for call to 'contains<list.std::initializer_list<int>::begin(), list.std::initializer_list<int>::end()>(int)'
     cout << contains<list.begin(), list.end()>(2);
                                                 ^
main.cpp:10:6: note: candidate: 'template<const int* begin, const int* end> bool contains(int)'
 bool contains(int v)
      ^~~~~~~~
main.cpp:10:6: note:   template argument deduction/substitution failed:
main.cpp:25:49: error: the address of '._86' is not a valid template argument
     cout << contains<list.begin(), list.end()>(2);
                                                 ^
main.cpp:25:49: error: 'list.std::initializer_list<int>::end()' is not a valid template argument for 'const int*' because it is not the address of a variable

I believe this could compile because the compiler has all the information at compile time: list is constexpr and so are its begin, end and next. So what prohibits this from working?

Upvotes: 3

Views: 159

Answers (1)

Brian Bi
Brian Bi

Reputation: 119164

The initializer list object holds a pointer to an array of 3 ints which actually have the values 1, 2, 3. When you call .begin(), a pointer to the first element (with value 1) is returned. However, you are not allowed to use a pointer to an array element as a template argument, since the standard specifies that a template parameter of pointer type shall not point to "a subobject" ([temp.arg.nontype]/2.1). I'm not sure why this restriction exists, though.

Upvotes: 5

Related Questions