【发布时间】:2018-10-19 19:52:03
【问题描述】:
我有一些编译器行为 - 在 VisualC++ 和 g++ 上有所不同 - 我不理解(对于任一编译器)。我会用英文描述它,但也许只看下面的代码会更容易。
它与具有成员类模板和成员函数模板的类模板有关。我正在尝试同时
- 显式特化外部类模板(不特化成员模板)
- 在外部类模板的显式特化内显式特化成员模板。
我发现,对于这两个编译器,如果我执行 任一 #1(显式特化外部类模板)或 #2(显式特化成员模板),一切都可以正常编译(并且实例化符合预期) .
但如果我尝试同时执行 #1 和 #2(我相信以正确的顺序声明),我会发现
- 使用 g++,我可以为成员类模板执行此操作,但在成员模板类声明中出现编译器错误。
- 对于 VC++,我得到两个成员模板的编译器错误。
这是外部类模板的主要定义。在以下所有情况下都是一样的:
// Class template with a member class template and a member function template
template <int I>
struct OuterClass
{
template <int J> struct InnerClass {};
template <int J> static void InnerFunc() {}
};
这里只做#1(明确专门化外部类模板)。这编译得很好并且实例化符合预期。
// Explicit specialization of outer class template,
// leaving member templates unspecialized.
template <>
struct OuterClass<1>
{
template <int J> struct InnerClass {};
template <int J> static void InnerFunc() {}
};
这里只做#2(明确专门化成员模板)。这编译得很好并且实例化符合预期。
// Explicit specialization of inner templates for
// an explicit specialization of outer class template
template <> template <> struct OuterClass<1>::InnerClass<1> {};
template <> template <> void OuterClass<1>::InnerFunc<1>() {}
这里尝试同时执行 #1 和 #2 - 只需将之前的两个代码 sn-ps 粘贴在一起即可:
// Explicit specialization of outer class template,
// leaving member templates unspecialized.
template <>
struct OuterClass<1>
{
template <int J> struct InnerClass {};
template <int J> static void InnerFunc() {}
};
// Explicit specialization of inner templates for
// an explicit specialization of outer class template
template <> template <> struct OuterClass<1>::InnerClass<1> {}; // Line A
template <> template <> void OuterClass<1>::InnerFunc<1>() {} // Line B
g++ 可以很好地编译“A 行”(并且实例化符合预期)。但是 g++ 给出了 B 行的编译器错误:“模板参数列表太多”。
VC++ 为“A 行”和“B 行”都给出了编译器错误(这里太杂乱了,不胜枚举)。
同样,对于两个编译器,“A 行”和“B 行”都可以正常编译,因为它们在外部类模板的显式特化之后没有出现。
据我了解,一切都应该编译得很好。那么谁是对的——我、g++ 还是 VC++?更重要的是,为什么?
请理解这不是一个“我如何完成 X”的问题,这是一个“我想完全理解 C++”的问题。如果您花时间阅读并考虑一下,我会感谢您...我希望我尽可能地简化它。
【问题讨论】:
-
如果我确定的话,我会回答这个问题。但我以前从未见过双重
template<> template<>。使用单个template<>它可以很好地与 Microsoft ms140 一起编译。 -
@lakeweb 在 gcc 和 clang 中也是如此。然而,在 C++ 草案中的“模板->模板实例化和专业化->显式专业化”部分的 pt 14-15 中有“模板模板”的示例(其数量因版本而异)
-
嗨@max360 谢谢。所以我通读了this,它更有意义。我找不到规则,但似乎知道您不能复制专业化。因此,使用双
template<>是对新专业化的请求,struct OuterClass<1>已经完成。我接近了吗? -
@lakeweb 感谢您的回复,您是对的,单个模板 使用 MSVC 编译,同时存在 #1 和 #2。这让我朝着正确的方向开始,我想我明白了 - 请在下面查看我的自我回答。正如 max630 指出的那样,有时“模板”的多次出现是合法的(并且是必需的) - 另请参见我的答案中的代码示例和 en.cppreference.com/w/cpp/ 底部的示例语言/模板专业化。
标签: c++