在包含另一个模板类的模板类中(对于它重要的东西,可交换的存储表示......无论如何),我认为不是传递几个模板参数向下,而是更优雅地传递内部模板的一个实例并再次到达参数向上。
为什么不呢!当然这很有效,而且它更优雅!
现在,上面的内容可能有点难以理解,所以让我们看一下(几乎可编译的)我一直试图做的代码:
template<typename T, int n> struct foo
{
// using alias_of_T = T;
};
template<typename FOO> struct bar
{
FOO _foo;
// this works just fine!?
static constexpr int size = FOO::n;
// this indeed works, but... bleh
// using type_t = typename FOO::alias_of_T;
// this does not work?
using type_t = typename FOO::T;
type_t whatever() { return ...; }
};
//...
int main()
{
bar<foo<int, 3>> zoo;
...
令人惊讶的是FOO
的模板参数T
无法访问。但更令人惊讶的是,完全可以访问n
。
背后的理由是什么?
是否比使用FOO::alias_of_T
更优雅?
事实证明,我读取自己的代码太愚蠢了! (@Barry的荣誉)确实是一个&#34;不同的大小&#34;,即原始(未修剪,非foo-bar)代码中的constexpr size = n
别名,我似乎完全没有忽视。这就解释了为什么它可以正常工作&#34;对于非类型参数,没有惊喜。嗯,那令人尴尬,你真的必须能够正确阅读你自己输入的代码......
答案 0 :(得分:8)
令人惊讶的是
FOO
的模板参数T
无法访问。但更令人惊讶的是,完全可以访问n
。
我认为这取决于你对完美的定义。它实际上无法访问n
,但您发现这一点的方式略有不同。实际上,如果您尝试使用 size
:
#include <iostream>
template <typename T, int n>
struct foo { };
template <typename FOO>
struct bar {
static constexpr int size = FOO::n;
};
int main() {
bar<foo<int, 3>> zoo;
std::cout << zoo.size << '\n'; // error: n is not a member of foo<int, 3>
}
这是因为[temp.inst]/3:
特别是,静态数据成员的初始化(以及任何相关的副作用)不会发生,除非静态数据成员本身的使用方式需要静态数据成员的定义存在
在您的示例中,静态数据成员不需要存在任何内容,因此它的初始化尚未发生 - 而且它的初始化可能是错误的。
如果您直接尝试访问名称&#34; n&#34;,您会看到同样的事情:
template <typename T, int n>
struct foo { };
template <typename FOO>
struct bar {
int array[FOO::n]; // error
};
int main() {
bar<foo<int, 3>> zoo;
}