编译器将(不相关)模板的名称与方法名称混淆



我在以下代码中有一个编译错误。编译器似乎将类方法set解释为模板,乍一看,该模板与我的代码完全无关。

#include <cassert>
#include <limits>
using namespace std;
template <class T>
class ReduceScalar{
    public:
        T get() { return *r; };
        void set(T t) { *r = t; };
        void set(T* t) { r = t; };
    private:
        T* r;
};
template <class T>
class ReduceSum : public ReduceScalar<T>
{
    public:
        ReduceSum(T* target) { set(target); set(0); } // COMPILE ERROR

};

编译器给出以下错误:

../test/../io/scalarreducers.h:34:26: error: use of class template 'set' requires template arguments
                ReduceSum(T* target) { set(target); set(0); }

但我认为这是因为它认为set是一个模板:

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__tree:685:71: note: template is declared here
        template <class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY set;

我不明白为什么编译器试图为方法set实例化该模板,而不仅仅是调用方法 set .如何解决此名称混淆?

即使你摆脱了那个讨厌的using namespace std,你仍然会遇到问题。问题是成员函数set可能并不存在于所有实例中。问题中的代码使用 set 作为非限定的非依赖名称。这意味着两件事:

  • 编译器将尝试在定义模板的位置解析set
  • 编译器不会查看成员函数set的基类ReduceScalar<T>。它不能,因为该成员可能并非对所有实例都存在。

最终结果:代码无法编译。解决方案是将该非依赖名称转换为依赖名称。这会将依赖名称的解析推迟到模板实例化。执行此操作的一种方法是显式使用 this(这是一个依赖名称)。

template <class T>
class ReduceSum : public ReduceScalar<T>
{
public:
    ReduceSum(T* target) { this->set(target); }
};

或者,您可以使用 using 声明(与 using 指令有很大不同):

template <class T>
class ReduceSum : public ReduceScalar<T>
{
public:
    using ReduceScalar<T>::set;
    ReduceSum(T* target) { set(target); }
};

相关内容

  • 没有找到相关文章

最新更新