这个显式模板函数是否对类模板的成员模板的成员模板有效?

时间:2013-12-03 23:27:53

标签: c++ templates language-lawyer template-specialization specialization

有没有人知道这种明确的专业化是否有效:

template <class>
struct L {
  template <typename T>
  struct O {
    template <typename U>
    static void Fun(U);
  };
};

template<>
template<typename T>
template<typename U>
void L<int>::O<T>::Fun(U) {}

clang trunk(12/3/2013)给出以下错误:
f:... \ test.cpp:36:20:错误:没有定义的“O”类的“Fun”的外线定义

void L<int>::O<T>::Fun(U) {}
     ~~~~~~~~~~~~~~^

生成了1个错误。

非常感谢来自标准的任何支持性参考以证明您的答案:

注意:我有点惊讶这是一个错误 - 我希望能够为任何一系列模板参数挑选专门化,其中'Fun'以<int><?any><?any>.开头实例化

这是一个铿锵的bug还是我期望的错误?

谢谢!

======编辑(我想我有答案)========

好的 - 我想我找到了支持措辞 - 来自N3797(芝加哥后2013年工作草案) - 14.7.3 / 16 =&gt;

“在类模板成员或出现在命名空间作用域中的成员模板的显式特化声明中,成员模板及其某些封闭类模板可能保持非专业化,但声明不应明确专门化类成员模板,如果它的封闭类模板也没有明确专门化。“

如果我正确地解释了这个,如果我们要声明其成员的显式特化,我们需要O的显式特化?因此错误。

正确?

谢谢!

1 个答案:

答案 0 :(得分:4)

我不相信它是有效的。我没有足够的语言来告诉你如何在不提供如下所述的顶级专业化的情况下完成此操作,或者如果有跳过复制模板的快捷方式,但错误消息相当清楚:您试图提供依赖嵌套类型的静态成员的实现,而不提供实际依赖项的特化。即这有效:

#include <iostream>

template <typename>
struct L
{
    template <typename T>
    struct O
    {
        template <typename U>
        static void Fun(U)
        {
            std::cout << "General: " << __PRETTY_FUNCTION__ << std::endl;
        };
    };
};

// provide specialized L
template<>
struct L<int>
{
    template <typename T>
    struct O
    {
        template <typename U>
        static void Fun(U);
    };
};

// L<int> is a specialized type, so provide the rest.
template<typename T>
template<typename U>
void L<int>::O<T>::Fun(U)
{
    std::cout << "Special: " << __PRETTY_FUNCTION__ << std::endl;
}


int main()
{
    L<int>::O<double> nobj;
    nobj.Fun(10);

    L<double>::O<int> nobj2;
    nobj2.Fun(20);

    return 0;
}

<强>输出

Special: static void L<int>::O<double>::Fun(U) [T = double, U = int]
General: static void L<double>::O<int>::Fun(U) [T = int, U = int]