非类型模板参数的占位符类型在模板模板参数的情况下是否可以互换
Are placeholders types of non-type template parameters interchangeable in case of template template parameter
考虑一个简单的例子:
int x;
template <template <auto> class TT>
struct Foo {
void foo() {
TT<(x)> tt;
static_cast<void>(tt);
}
};
template <decltype(auto)>
struct Bar { };
int main() {
Foo<Bar> foobar;
foobar.foo();
}
[clang] 似乎处理了decltype(auto)
占位符的想法,尽管在模板模板参数声明中使用了auto
没有问题。
[GCC] 另一方面 - 不是很好:
prog.cc:6:13:错误:"x"的值在常量表达式中不可用
像往常一样 - 根据标准,哪些行为是预期的?或者也许一切皆有可能并且代码格式不正确(这次我想不是,但不能明确排除)?
很抱歉再次破坏其中一个编译器;)
这里的原始答案Foo<Bar>
格式不正确,我现在实际上认为它的格式很好。但最终,基于叮当错误。
我实际上认为即使是遵循P0522的新规则是:Foo<Bar>
也是格式错误的。
A
一样专业时,模板参数P
P
与模板参数匹配
哪里:
模板模板参数P
至少与模板模板参数一样专用,
A
如果给定以下重写为两个函数模板,则根据函数模板的部分排序规则 ([temp.func.order]),对应于P
的函数模板至少与对应于A
的函数模板一样专用。给定一个发明的类模板X
模板参数列表A
(包括默认参数):
- 两个函数模板中的每一个都具有相同的模板参数,分别为
P
或A
。- 每个函数模板都有一个函数参数,其类型是
X
的专用化,模板参数对应于相应函数模板中的模板参数,其中,对于函数模板的模板参数列表中的每个模板参数PP
,形成相应的模板参数AA
。如果PP
声明了一个参数包,则AA
是包扩展PP...
([temp.variadic]);否则,AA
是id 表达式PP
。如果重写生成无效类型,则
P
至少不像A
那样专业。
这意味着为了验证Foo<Bar>
本身是否正常,我们合成:
template <decltype(auto) I> struct X;
template <auto I> void __f(X<I> ); // P
template <decltype(auto) I> void __f(X<I> ); // A
此处的所有类型都是有效的(因此最后一个语句不适用)。现在,通常当我们进行部分排序时,它是在重载解析或选择类模板专用化的上下文中,在这种情况下,我们正在寻找的是"更专业"的函数模板,其中F
比G
更专业,如果F
至少与G
一样专业,而G
至少不像F
那样专业。
但在这种情况下,我们不关心哪个更专业。我们只需要P
至少像A
一样专业.所有这些都意味着演绎必须从A
成功到P
。那么如果我们合成一些具有一些值V
的独特类型U
,我们可以从X<V>
中推断出X<I>
吗?是的。因此,P
至少和A
一样专业,所以模板参数Bar
与模板参数TT
匹配。
现在,通过这一点,我会说这是一个叮当声。模板参数是template <auto>
,这是我们应该用来验证表达式的。对于非类型模板参数auto
,我们会尝试使用x
作为值 - 但x
不是有效的常量表达式,所以这应该会失败。clang 似乎直接使用template <decltype(auto) >
- 我不确定这是否有效。
也就是说,我不确定这个案子是否被考虑过——我没有看到任何措辞,值得提出一个问题。
- 扩展C++生成的代码的模板参数类型名称
- 如何在 c++ 中定义接受不同参数类型的函数向量?
- 在 C++ 中运行时调用模板时,是否可以切换模板的参数类型?
- 将函数参数类型声明为 auto
- 将函数的参数 - 签名从使用 'std::function<T>' 转换为模板参数类型
- 在 C++17 中调用具有不同参数类型的构造函数
- 具有先前参数类型匹配的参数包
- 我想知道为什么"std::unique_ptr<int> foo(新 int)"是合法的,因为"std::<int>unique_ptr"要求输入参数类型应该是"int"?
- 将可变参数类型列表的扩展打包为复杂类型的初始值设定项列表 - 合法吗?
- MSVC 错误:4 个重载中的任何一个都无法转换所有参数类型
- 使用constexpr + auto作为返回和参数类型的奇怪类型推导
- 如何从第一个参数推断第二个参数类型?
- C++模板函数中,指定回调函子/lambda 的参数类型,同时仍允许内联?
- 如何用不同的参数类型和数字回调函数
- C++stoi:这两个重载都无法转换所有参数类型
- 为什么std::{container}::template不能推导其参数类型
- 为模板参数类型中的新对象分配内存
- 为指向成员模板参数的指针推导额外模板参数类型的紧凑方式
- 使用std::conditional中的模板来确定函数参数类型
- C++中的短参数类型