关于模板:C ++运算符重载分辨率模糊

C++ operator overloading resolution ambiguity

我试图把一个古董C++代码库从GCC 3.2移到GCC 4.1,因为我遇到了一些问题。在所有这些问题中,下面的内容让我感到茫然(我想我花了太多时间在Java上,或者我可能忘记了C++的基础知识:-P)。

我有一个模板类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
template < class T > class XVector < T >
{
   ...
   template < class T > T
   XVector < T >::getIncrement ()
   {
       ...
   }  
   template < class T > int
   XVector < T >::getValue (size_t index, T& value)
   {
      ...
      //The problematic line
      value = (T) (first_value + getIncrement())
                  * (long) (index - first_index);
      ....
   }
}

这个类基于STL STD::vector。我有一个第二类类型的值,它定义为下面的一个,它可以保存int、Load和它们的未签名变量之一,浮点、双数、STD::字符串。也会重载几乎所有可能的运算符。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class TypeValue
{
    union
    {
        long* _int_value;
        double* _real_value;
        string* _text_value;
    } _value;

    TypeValue();
    explicit TypeValue(long _long);
    explicit TypeValue(int _int);
    explicit TypeValue(unsigned long _ulong);
    ...
    //similarly for all the remaining supported types.
    TypeValue(const TypeValue& ) //Copy constructor

    virtual TypeValue& operator=(const TypeValue &rhs);
    TypeValue& operator+ (TypeValue& )const;
    TypeValue& operator* (TypeValue& )const;
    ...
    //For all the basic operators

    operator long() const;
    operator int() const;
    operator unsigned long() const;
    operator unsigned int() const;
    ...

}

最后我还有另一个类,我们称它为build-breaker,它创建一个对象作为XVector < TypeValue > a_variable;。现在,当我在GCC 3.2上编译这个代码时,它没有任何问题。但是当我尝试在GCC4.1上编译这个代码时,我发现错误的说法是:在XVector类中,operator*的ambigous重载,而候选代码是

1
2
3
4
5
6
operator*(long int, long int)
operator*(int, long int)
operator*(long unsigned int, long int)
operator*(unsigned int, long int)
operator*(double, long int)
operator*(float, long int)

如果编译器说它找不到t*long的匹配项,这是有道理的,但是,为什么它要将其类型转换为本机类型,然后执行算术操作呢?请帮我一下。

事先谢谢。


第二个操作数类型是long [int]。第一个是TypeValue,我想,但是没有一个运算符*可以使用这两种类型。不过,该运算符还有许多其他类型组合,编译器可以通过对第一个操作数执行隐式转换来选择这些类型组合。该语言允许编译器这样做,以尝试找到匹配项。

但在众多的转换中,它应该选择哪一种呢?编译器无法选择int是否优于long int。(您可能会认为,由于第二个操作数是long int,所以这应该是首选的转换目标,但这不是工作方式。)

所以,一些建议:首先,不要提供这么多的隐式转换。因为这个类只能容纳longdoublestring,所以我只提供三种转换。仅此一项可能无法解决您的问题,但它可能会减小错误输出的大小,并使其他事情更易于管理。

不要将(index - first_index)转换为long类型,而是考虑将其转换为T类型(即TypeValue类型),因为这似乎是您最初真正想要执行的操作。


我会将所有转换运算符更改为命名函数,以便:

1
operator long() const;

变成

1
long ToLong() const;

通过CAST运算符隐式转换会导致各种问题,我自己的编程标准禁止使用它们。


我们需要知道T是什么。看起来您正在使用某种类型(例如无符号字符)来实例化XVector,这种类型可以转换为您看到的所有类型,而编译器不知道要选择哪种类型。