PxxxxR0
consteval template instantiation

New Proposal,

This version:
http://virjacode.com/papers/consteval_template_instantiation000.htm
Latest version:
http://virjacode.com/papers/consteval_template_instantiation.htm
Author:
TPK Healy <healytpk@vir7ja7code7.com> (Remove all sevens from email address)
Audience:
SG17
Project:
ISO/IEC 14882 Programming Languages — C++, ISO/IEC JTC1/SC22/WG21

Abstract

Allow consteval functions to instantiate templates using function arguments as template arguments. Allow the same for constexpr functions invoked in a constant-evaluated context.

Note: A change is required to the core language.

1. Introduction

The following code is currently ill-formed in C++23:

template<int i>
bool TempFunc(void)
{
    return 42 == i;
}

constexpr bool Func(int const a)
{
    if consteval
    {
        return Func<a>();    // compiler error
    }
    else
    {
        return false;
    }
}

It is ill-formed because the function argument, a, cannot be used to instantiate the template function TempFunc.

This paper proposes a solution to this debacle by amending the core language to allow in cases of functions invoked in a constant-evaluated context the function arguments, and also local variables, to be used to instantiate templates.

2. Motivation

2.1. Compile-time strings

It is currently possible to write a template function that returns an std::array<char, N> which is the concatenation of all the strings passed to it as arguments, as follows:

template<size_t... N>
consteval auto Concat(char const (&... strings)[N])
{
    constexpr size_t sum = ((N-1u) + ...);
    std::array<char, sum+1u> retval{};
    size_t index = 0u;
    ((std::copy_n(strings, N-1u, retval.begin() + index), index += N-1u), ...);
    retval[sum] = '\0';
    return retval;
}

It is not possible however to write a consteval function that achieves the same goal, as the following code is ill-formed:

consteval auto Concat(std::initializer_list<std::string_view> const args)
{
    size_t sum = 0u;
    for ( auto const sv : args ) sum += sv.size();
    std::array< char, sum + 1u > retval{};
    size_t index = 0u;
    for ( auto const sv : args )
    {
        std::copy(sv.cbegin(), sv.cend(), retval.begin() + index);
        index += sv.size();
    }
    retval[sum] = '\0';
    return retval;
}

The above snippet is ill-formed because of the following line:

std::array< char, sum + 1u > retval{};

It is not possible in C++23 to use the value of the local variable sum to instantiate a template. This paper proposes that this should be possible in C++26.

. . . . Write more here about why we want a consteval function instead of a template function, e.g. a map with string keys . . . .

3. Design considerations

To be written later. . .

4. Proposed wording

To be written later. . .

5. Impact on the standard

This proposal is a change to the core language. The change to the core language is a paragraph to be added to ________________. The addition has no effect on any other part of the standard.

6. Impact on existing code

No existing code becomes ill-formed. The behaviour of all existing code is unaffected.