使用 struct 本身作为模板参数是否合法?
Is it legal to use struct itself as template argument?
根据 cppreference.com 上的 Template parameters and template arguments:
A template argument for a type template parameter must be a type-id,
which may name an incomplete type
这意味着这个例子(从那个页面复制)是合法的:
// Example 0
template <typename T>
struct X {};
struct A;
int main() {
X<A> x1;
}
而且,我想,这也是合法的:
// Example 1
template <typename T>
struct X {};
struct A {
X<A> x1;
};
int main() {
A a1;
}
现在,让我们把代码复杂一点:
// Example 2
template <typename T>
struct X {
using type = typename T::type;
};
struct A {
using type = int;
X<A>::type x1;
};
int main() {
A a1;
}
在这种情况下,A
在用作模板参数时仍然是一个不完整的类型,并且代码可以编译。现在,如果我更改 A
:
中行的顺序
// Example 3
template <typename T>
struct X {
using type = typename T::type;
};
struct A {
X<A>::type x1; // ERROR HERE
using type = int;
};
int main() {
A a1;
}
代码不再编译。 Clang 错误消息类似于 no type named 'type' in 'A'
,还有 GCC、ICC 和 MSVC return 类似的错误(参见 this demo on godbolt.com), and this seems almost identical to that of typedefs on CRTP, discussed here.
无论如何,这种行为似乎是合理的:编译器使用在使用 X<A>
时定义的 A
的所有属性。
但是 C++14(或更高版本)标准对此有何规定?依赖工作示例2的行为是否合法?
你可以看看那里的推理,但我的理解是,共识是目前技术上的标准不允许你的最后一个或 second-to-last 示例,因为 second-to-last 的实例化点=10=]会在A
的定义之前,其中typename T::type
无法形成。
但是,如提议的决议中所示,即使实例化点在 A
的定义之前,但在 A
中声明的名称在需要实例化的点之前X<A>
实例化仍然可见。
这就是编译器实现的,您会观察到。
根据 cppreference.com 上的 Template parameters and template arguments:
A template argument for a type template parameter must be a type-id, which may name an incomplete type
这意味着这个例子(从那个页面复制)是合法的:
// Example 0
template <typename T>
struct X {};
struct A;
int main() {
X<A> x1;
}
而且,我想,这也是合法的:
// Example 1
template <typename T>
struct X {};
struct A {
X<A> x1;
};
int main() {
A a1;
}
现在,让我们把代码复杂一点:
// Example 2
template <typename T>
struct X {
using type = typename T::type;
};
struct A {
using type = int;
X<A>::type x1;
};
int main() {
A a1;
}
在这种情况下,A
在用作模板参数时仍然是一个不完整的类型,并且代码可以编译。现在,如果我更改 A
:
// Example 3
template <typename T>
struct X {
using type = typename T::type;
};
struct A {
X<A>::type x1; // ERROR HERE
using type = int;
};
int main() {
A a1;
}
代码不再编译。 Clang 错误消息类似于 no type named 'type' in 'A'
,还有 GCC、ICC 和 MSVC return 类似的错误(参见 this demo on godbolt.com), and this seems almost identical to that of typedefs on CRTP, discussed here.
无论如何,这种行为似乎是合理的:编译器使用在使用 X<A>
时定义的 A
的所有属性。
但是 C++14(或更高版本)标准对此有何规定?依赖工作示例2的行为是否合法?
你可以看看那里的推理,但我的理解是,共识是目前技术上的标准不允许你的最后一个或 second-to-last 示例,因为 second-to-last 的实例化点=10=]会在A
的定义之前,其中typename T::type
无法形成。
但是,如提议的决议中所示,即使实例化点在 A
的定义之前,但在 A
中声明的名称在需要实例化的点之前X<A>
实例化仍然可见。
这就是编译器实现的,您会观察到。