给定以下类模板:
template<typename T>
struct Outer
{
struct Inner;
auto f(Inner) -> void;
};
Run Code Online (Sandbox Code Playgroud)
我们Inner为以下每种专业分别定义Outer:
template<>
struct Outer<int>::Inner {};
template<>
struct Outer<double>::Inner {};
Run Code Online (Sandbox Code Playgroud)
然后f为以下所有专业定义一次成员函数Outer:
auto Outer<T>::f(Inner) -> void
{
}
Run Code Online (Sandbox Code Playgroud)
但是Clang(9.0.0)抱怨:
error: variable has incomplete type 'Outer::Inner'
auto Outer<T>::f(Inner) -> void
^
Run Code Online (Sandbox Code Playgroud)
我们还可以通过提供Inner以下所有其他专业的定义来规避编译器错误Outer:
template<typename T>
struct Outer<T>::Inner {};
Run Code Online (Sandbox Code Playgroud)
或通过f为每个专业分别定义:
template<>
auto Outer<int>::f(Inner) -> void
{
}
template<>
auto Outer<double>::f(Inner) -> void
{
}
Run Code Online (Sandbox Code Playgroud)
GCC和MSVC都接受初始代码,这就是问题所在。这是Clang错误,还是这三个中唯一的一致实现?
c++ templates template-specialization language-lawyer incomplete-type
以下荒谬的示例无法编译,但是还有其他方法可以将变量模板作为模板模板参数传递吗?
template<typename T>
constexpr auto zero = T{0};
template<typename T, template<typename> auto VariableTemplate>
constexpr auto add_one()
{
return VariableTemplate<T> + T{1};
}
int main()
{
return add_one<int, zero>();
}
Run Code Online (Sandbox Code Playgroud)
以下内容无法在GCC 9.1(支持类非类型模板参数)上编译
struct S { int i; };
template<S s>
struct T {};
int main()
{
T<{0}> x{};
}
Run Code Online (Sandbox Code Playgroud)
error: could not convert '{0}' from '<brace-enclosed initializer list>' to 'S'尽管template参数s为具体类型,但编译器仍会报告S。
T<S{0}> x{};
Run Code Online (Sandbox Code Playgroud)
可以按预期工作,但是C ++ 2a S是否可以像在该语言的其他部分一样允许省略具体的类型名称?