【问题标题】:Template specializations for inner class内部类的模板特化
【发布时间】:2016-11-15 16:19:10
【问题描述】:

考虑以下代码:

struct X
{
    template <typename T>
    class Y
    {};
 };
template<>
class X::Y<double>{
};

这里我们将 Y 类专门用于 double 类型,并且代码工作正常。问题是,如果我将代码更改为:

template<typename A>
struct X
{
    template <typename T>
    class Y
    {};
 };
template<typename A>
class X<A>::Y<double>{
};

编译器会报错:

'X::Y': 显式特化正在使用部分 特化语法,使用模板 代替!

有谁知道在这种情况下我如何专攻 Y 类?

【问题讨论】:

  • 执行错误消息所说的没有帮助吗?在嵌套模板特化中使用 template&lt;&gt; 而不是 template&lt;typename A&gt;。
  • 它不起作用!我也厌倦了这个:template class X::Y{ };

标签: c++ metaprogramming template-specialization


【解决方案1】:

如果没有明确地特化外部模板类,您就无法特化一个内部模板类。 See this question for more details and a quote from the standard.

解决方法:创建一个外部类,该类在详细命名空间中同时采用T 和A,并在X 中为其取别名:

namespace impl
{
    template <typename A, typename T>
    struct Y { };
}

template<typename A>
struct X
{
    template <typename T>
    using Y = impl::Y<A, T>;
};

如果您可以明确地特化内部类和外部类,您可以使用以下语法:

template <>
template <>
class X<int>::Y<double>
{
    // ...
};

Example on wandbox

【讨论】:

  • 如果我想将它专门用于特定的 X 和 Y,例如:template class X::Y{ };在这种情况下,它也会抱怨!它说:error C2992: 'X::Y': invalid or missing template parameter list
  • @MEMS:你需要双重template&lt;&gt;。 Example on wandbox.
  • 也更新了我的答案。
【解决方案2】:

简单的答案 - 您不能完全专门化模板化外部类的模板化内部类。但如果你真的想达到类似的效果,你可以尝试使用虚拟默认模板参数进行部分特化:

#include <iostream>

template<typename A>
struct X
{
    template <typename T, T* =nullptr>
    class Y{};
 };

template<typename A>
template<double *Ptr>
class X<A>::Y<double, Ptr> {
public:
    static constexpr int value = 1;
};

int main() {
    std::cout << X<int>::Y<double>::value << std::endl;
}

[live demo]

【讨论】:

  • 这本书:经典 c++ 中的高级元编程,第 33 页说:模板特化仅在命名空间级别有效:struct X { template class Y {}; template // 非法,但编译器通常可以容忍 class Y {}; }; template // 合法类 X::Y { };所以你所做的可能会奏效,但并非总是如此!
  • @MEMS 你的作者可能是对的。在寻找标准示例后,我意识到我实际上可能过度解释了[temp.class.spec] /5。更新代码
  • @MEMS 根据 C++ 标准核心语言活动问题727. In-class explicit specializations 成员类的内联部分专业化结构良好......所以我之前的代码确实有效。请找reference
猜你喜欢
  • 2015-11-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多