g ++无法选择正确的方法

时间:2016-04-24 17:07:34

标签: c++

我很困惑为什么编译器(g ++ ver 4.8.4)在编译以下代码片段时遇到问题。在调用x.addField("hi", s.size());中,我认为编译器可以简单地使用方法void addField(const char *fieldName, long value),因为它显然是最佳匹配。

#include <string>
#include <iostream>
#include <stdlib.h>
#include <stdio.h>

using namespace std;

class strDum {
public:
    void addField(const char *fieldName, const char *fmt, ...);
    void addField(const char *fieldName, bool value);
    void addField(const char *fieldName, long value);
    void addField(const char *fieldName, double value);
};

void strDum::addField(const char *fieldName, const char *fmt, ...) {
}
void strDum::addField(const char *fieldName, bool value) {
}
void strDum::addField(const char *fieldName, long value) {
}
void strDum::addField(const char *fieldName, double value) {
}

int main(int argc, char *argv[] )
{
    string s = "hello";
    strDum x;
    x.addField("hi", s.size());
    return 0;
}

这是编译器错误消息

$ g++ -std=c++11 te4.cc
te4.cc: In function ‘int main(int, char**)’:
te4.cc:29:27: error: call of overloaded ‘addField(const char [3], std::basic_string<char>::size_type)’ is ambiguous
  x.addField("hi", s.size());
                           ^
te4.cc:29:27: note: candidates are:
te4.cc:16:6: note: void strDum::addField(const char*, const char*, ...) <near match>
 void strDum::addField(const char *fieldName, const char *fmt, ...) {
      ^
te4.cc:16:6: note:   no known conversion for argument 2 from ‘std::basic_string<char>::size_type {aka long unsigned int}’ to ‘const char*’
te4.cc:18:6: note: void strDum::addField(const char*, bool)
 void strDum::addField(const char *fieldName, bool value) {
      ^
te4.cc:20:6: note: void strDum::addField(const char*, long int)
 void strDum::addField(const char *fieldName, long value) {
      ^
te4.cc:22:6: note: void strDum::addField(const char*, double)
 void strDum::addField(const char *fieldName, double value) {
      ^

有什么想法吗?

1 个答案:

答案 0 :(得分:3)

此调用中的参数:

x.addField("hi", s.size());

{const char[3], size_t}类型。对于这组参数,我们有三个可行的重载候选者:

void addField(const char*, bool );
void addField(const char*, long );
void addField(const char*, double );

在每种情况下,size_t都可以通过积分转换(size_tboolsize_tlong)转换为第二种参数类型,或者浮动积分转换(size_tdouble)。这些转换都没有比其他转换更好 - 它们都具有相同的排名:转换。因此,没有最佳可行的候选人,因为我们无法区分这三个选项。

混淆的一个原因可能是longsize_t“更接近”bool。但从转换排名的角度来看,这无关紧要。它们都涉及积分转换,并且在不同的积分转换类型之间没有区别 1

消除歧义:

  • 提供新的重载:addField(const char*, size_t)
  • 将第二个参数转换为您想要的类型 - x.addField("hi", static_cast<long>(s.size()))
  • 将所有重载折叠为函数模板:template <class T> void addField(const char*, T)

可能你会想要最后一个。

1 促销(例如charint)和积分之间的区别转换虽然(例如intchar)。促销是比转化更好的转化。