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

Dam*_*mon 1 c++ templates c++17

在包含另一个模板类的模板类(什么重要的...可更换存储表示什么),我认为这不是在serveral的模板参数传递下来,那将是更优雅中的一个实例来传递内模板和参数达到再次来代替.

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

现在,也许上面的内容有点难以理解,所以让我们看看我一直在努力做的一些(几乎可编译的)代码:

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;
    ...
Run Code Online (Sandbox Code Playgroud)

令人惊讶的是,FOO模板参数T无法访问.但更令人惊讶的是,完全可以访问n.

这背后的理由是什么?

有比使用更优雅的方式FOO::alias_of_T吗?

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

事实证明,我太愚蠢了,无法阅读我自己的代码!有(对@Barry的称赞)确实是一个"不同大小",即constexpr size = n原始(不是修剪,非foo-bar)代码中的别名,我似乎完全忽略了这些代码.这就解释了为什么它对非类型参数"工作正常",这并不奇怪.嗯,这很尴尬,你真的能够正确阅读你自己键入的代码......

Bar*_*rry 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>
}
Run Code Online (Sandbox Code Playgroud)

这是因为[temp.inst]/3:

[...]特别是,除非静态数据成员本身以需要静态数据成员的定义存在的方式使用,否则不会发生静态数据成员的初始化(以及任何相关的副作用).

在你的例子中,没有任何东西需要静态数据成员存在,所以它的初始化还没有发生 - 而且这是初始化本来就是错误的.

如果您直接尝试访问名称"n",您会看到同样的事情:

template <typename T, int n>
struct foo { };

template <typename FOO>
struct bar {
    int array[FOO::n]; // error
};

int main() {
    bar<foo<int, 3>> zoo;
}
Run Code Online (Sandbox Code Playgroud)