我有一个用于卷对象的模板化类,其中operator+=
被实现为成员函数,而operator+
被实现为非成员函数:
template <typename Class>
Class operator+(Class c1, const Class& c2) {
return c1 += c2;
}
// Add a constant to every element in the volume
template <typename Class, typename dataType>
Class operator+(Class c, dataType constant) {
return c += constant;
}
template <typename Class, typename dataType>
Class operator+(dataType constant, Class c) {
return c += constant;
}
然后我尝试编译以下内容:
volume + 1.3;
其中volume是模板化卷类的派生类型。 这给了我以下错误:
error: ambiguous overload for ‘operator+’ in ‘volume + 1.3’
为什么电话不明确?
答案 0 :(得分:4)
可以使用Class = typeof(volume)
和dataType = double
推断您的第二个模板,或者可以使用dataType = typeof(volume)
和Class = double
推断您的第三个模板。编译器无法在它们之间进行选择,即使很可能第三个模板无法实例化。
我假设volume
具有用户定义的类型。如果它有一个内置类型,那么我不会认为调用是不明确的,因为仅为了运算符重载解析的目的,有“实际”函数double operator+(double, double);
等,即使在考虑模板之前也会选择它。
答案 1 :(得分:2)
假设Volume是您班级的名称。
Volume volume;
当需要解析卷+ 1.3时,编译器会寻找合适的方法。 它找到了其中两个。
为什么?
这些定义中的文字“类”没有意义。即使您打算发生这种情况,它也不与'Volume'类相关。
因此,编译器将其视为: 1.
template <typename X, typename Y>
X operator+(X c, Y constant)
模板 Z算子+(Z常数,X c)
因此,这两个对于行
的编译器同样足够好volume+1.3
即:从(1):
Volume operator+(Volume c, double constant)
来自(2):
Volume operator+(Volume constant, double c)
现在,编译器的含糊不清。
解决方案:我只能看到您必须分别为每种卷类型定义这些运算符的解决方案。
答案 2 :(得分:0)
其他人解释了为什么你的代码不起作用。但总的来说,编写接受任何参数类型的函数模板是一个非常糟糕的主意。这只是要求含糊不清。
如果你有一个&#34;卷&#34;要使用operator +的类型,可以使它们继承一个公共基类,然后可以将其用作模板中的参数类型。
template<typename T>
struct VolumeBase {
T copy() const { return get(); }
T const& get() const { return static_cast<T const&>(*this); }
};
template <typename Class, typename Class>
Class operator+(VolumeBase<Class> const& c, VolumeBase<Class> const& c1) {
return c.copy() += c1.get();
}
template <typename Class, typename dataType>
Class operator+(VolumeBase<Class> const& c, dataType constant) {
return c.copy() += constant;
}
template <typename Class, typename dataType>
Class operator+(dataType constant, VolumeBase<Class> const& c) {
return c.copy() += constant;
}
不幸的是,您已经将参数副本移动到模板的主体中,但是如果它可以内联(对于这么简单的主体,我认为没有问题),那不是会损害表现。因此每个卷类都将定义为
class MyVolumeClass : public VolumeBase<MyVolumeClass> { ... };