这是一个类模板的成员模板的成员模板的显示具体化的函数模板有效吗?

5

有没有人知道这个显式特化是否有效:

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个错误。

如果您能提供标准中支持您答案的任何参考资料,将不胜感激!

注意:我有些惊讶这是一个错误——我希望对于任何以<int><?any><?any>开头实例化'Fun'的模板参数族,都会选择专门化。

这是clang的bug还是我的期望有问题?

谢谢!

====== 编辑(我认为我有了答案)=======

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

"在类模板的成员或命名空间范围内出现的成员模板的显式专门化声明中,成员模板及其一些封闭类模板可以保持未专门化状态,除非声明不明确地专门化类成员模板,如果其封闭类模板也没有明确专门化,则其封闭类模板不得明确专门化。"

如果我理解正确,如果我们要声明其成员的显式专门化,就需要O的显式专门化吗?因此出现了错误。

正确吗?

谢谢!


我认为你引用的文本并不相关;它说的是你不能专门化 L<X>::O<int>。而 L<int>::O<T> 则是可以的。 - M.M
我添加了“语言律师”标签,因为我想知道在标准中要求在允许这个特化之前必须重新定义L<int>::O的位置。 - M.M
1个回答

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]

我认为你只需要提供以下内容:template<> template<class T> struct L<int>::O { template<class U> static void Fun(U); }; - 但我仍然不确定为什么这是必要的? - Faisal Vali
你说得对,这样你就可以使用之前指定的函数的声明。如果我有机会(家里有点混乱),我会更新这个内容。 - WhozCraig

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接