模板化非类型模板参数的推导

303*_*303 6 c++ templates type-deduction c++20

f编译器是否应该能够推断出默认为的函数模板的非类型模板参数的类型n{}?C++20 标准中的哪个具体规则允许/强制执行此操作?

template<typename = int>
struct s {
    template<typename = int>
    struct n {};

    template<n = n{}>
    constexpr int f();
};
static_assert(requires { s{}.f(); }); // clang ok, gcc ok, msvc nope
Run Code Online (Sandbox Code Playgroud)

令人惊讶的是,MSVC由于某种原因接受以下代码,而其他编译器甚至不允许该语法。难道MSVC只是和它想象中的朋友在这里开个茶会吗?f并且,除了将 fromn的NTTP 类型更改为 之外,是否有适用于所有 3 个编译器的解决方法auto

template<typename = int>
struct s {
    template<typename = int>
    struct n {};

    template<n<typename> = n{}>
    constexpr int f();
};
static_assert(requires { s{}.f(); }); // clang nope, gcc nope, msvc ok
Run Code Online (Sandbox Code Playgroud)

实例


关于解决方法,一种方法是添加成员类型n并使用需求子句进行手动类型约束检查。这不是我正在寻找的解决方法类型,它增加了太多的臃肿并且太麻烦了。另外,仅仅为了避免其他一些编译器差异而必须向类型添加显式常量对我来说也不是特别有吸引力。

#include <concepts>

template<typename = int>
struct s {
    template<typename T = int>
    struct n { using type = T; };

    template<auto N = n{}>
    requires std::same_as<decltype(N) const,
        n<typename decltype(N)::type> const>
    constexpr int f();
};
Run Code Online (Sandbox Code Playgroud)

产生的错误MSVC

<source>(9): error C2672: 's<int>::f': no matching overloaded function found
<source>(6): note: could be 'int s<int>::f(void)'
<source>(9): note: 'int s<int>::f(void)': could not deduce template argument
for '__formal'
<source>(9): error C2607: static assertion failed
Run Code Online (Sandbox Code Playgroud)

Bri*_*ian 0

C++20 [temp.arg.nontype]/1 允许模板参数的类模板实参推导:

如果模板参数T的类型(13.2)包含占位符类型(9.2.9.6)或推导类类型的占位符(9.2.9.7),则参数的类型是为发明声明中的变量推导的类型x

T x = template-argument ;
Run Code Online (Sandbox Code Playgroud)

如果模板参数声明 (13.2)不允许推导的参数类型,则程序格式错误。

template-parameter n = n{}中,两个ns 是“推导类类型的占位符”。由第一个表示的模板参数的类型n应该从初始化器中推导出来n{},并赋予它类型n<int>

本段没有具体说明模板参数是否可以来自默认模板参数,但即使是 MSVC 也不认为这实际上是不允许的:当nf不嵌套在 中时,MSVC 很乐意接受它s

template<typename = int>
struct n {};

template<n = n{}>
constexpr int f();

static_assert(requires { f(); });  // MSVC is fine with this
Run Code Online (Sandbox Code Playgroud)

没有理由认为这会有所作为。MSVC 可能只是有一个错误。我不清楚如何解决它。