【问题标题】:Clang VS VC++:"error: declaration of 'T' shadows template parameter"Clang VS VC++:“错误:‘T’阴影模板参数的声明”
【发布时间】:2014-01-19 10:24:36
【问题描述】:

我试图在我的 Mac 上使用 clang 3.3 为 the classic copy&swap idiom 编译以下代码

template<typename T> class node{

private:
    node<T>* left;
    node<T>* right;
    T value;

public:
    friend void swap(node<T>&, node<T>&);
    // other stuff
}

但链接器抱怨。我现在明白我应该将函数声明为模板。但是如果我按照 MSDN 中建议的here 的样式进行操作,就会出现错误:

template <class T> class Array {
    T* array;
    int size;

public:template<class T>
    //...
    template <class T>
    friend Array<T>* combine(Array<T>& a1, Array<T>& a2);
};

我进行了复制粘贴,但出现以下错误:

te.cpp:33:19: error: declaration of 'T' shadows template parameter
template<class T>
               ^
te.cpp:4:17: note: template parameter is declared here
template <class T> class Array {
                ^
1 error generated.

这是一个clang错误吗? MSDN 网站建议它在 VC++ 下工作。

PS:我知道有两种解决方案:在模板类内部定义友元函数,如Stackoverflow文章中那样,或者在模板类内部按如下方式声明:

template <typename U> friend void swap(node<U>&, node<U>&);

但两者都困扰着我。第一个集群类的声明,而第二个授予友谊以交换不同的类型。

更新:第三种解决方案是使用带有特化的前向声明:

template <typename T> class node;
template <typename T> void swap (node<T>&, node<T>&);
template <typename T> class node{
    //...
    friend void swap<> (node<T>&, node<T>&);
};

这也适用于clang。

【问题讨论】:

  • 您对交换的定义在哪里?这可能是问题所在。
  • @zneak。哦,我是用模板实现的。如果您需要查看它template &lt;typename T&gt; void swap(node&lt;T&gt;&amp; a, node&lt;T&gt;&amp; b){ std::swap(a.left, b.left); std::swap(a.right, b.right); std::swap(a.value, b.value); }
  • 你的第一个 sn-p 在我看来是正确的......“但是链接器抱怨了。”修复它,而不是进一步破坏你的代码;P

标签: c++ templates llvm-clang


【解决方案1】:

我相信这就是您想要的(这恰好是您刚刚添加到问题中的第三个选项)

#include <utility>

template <typename T> class node;
template <typename T> void swap(node<T> & a, node<T> & b);

template<typename T> class node {
    private:
        node<T>* left;
        node<T>* right;
        T value;

    public:
        friend void swap<>(node<T>&, node<T>&);
};

template <typename T> void swap(node<T> & a, node<T> & b) {
    std::swap(a.left, b.left);
    std::swap(a.right, b.right);
    std::swap(a.value, b.value);
}

int main() {
    node<int> x, y;
    swap(x, y);
}

【讨论】:

  • 是的,行得通。谢谢。但我仍然想知道为什么 MSDN 代码在 VC++ 中有效,但在 clang 下无效。
  • @CloudyTrees:clang 用来阻止它的规则是:C++ 2011 [temp.local] 第 6 段:不应在其范围内重新声明模板参数(包括嵌套范围) .模板参数不得与模板名称同名。这可以在Sema::DiagnoseTemplateParameterShadow 方法中的clang source code 中找到。
猜你喜欢
  • 1970-01-01
  • 2018-05-02
  • 1970-01-01
  • 1970-01-01
  • 2017-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-15
相关资源
最近更新 更多