为什么模板类型参数不可见/不存在而非非类型参数?

时间:2017-12-28 14:26:36

标签: c++ templates c++17

在包含另一个模板类的模板类中(对于它重要的东西,可交换的存储表示......无论如何),我认为不是传递几个模板参数向下,而是更优雅地传递内部模板的一个实例并再次到达参数向上

为什么不呢!当然这很有效,而且它更优雅!

现在,上面的内容可能有点难以理解,所以让我们看一下(几乎可编译的)我一直试图做的代码:

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更优雅?

Re:为什么它适用于非类型参数?

事实证明,我读取自己的代码太愚蠢了! (@Barry的荣誉)确实是一个&#34;不同的大小&#34;,即原始(未修剪,非foo-bar)代码中的constexpr size = n别名,我似乎完全没有忽视。这就解释了为什么它可以正常工作&#34;对于非类型参数,没有惊喜。嗯,那令人尴尬,你真的必须能够正确阅读你自己输入的代码......

1 个答案:

答案 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;
}