2012-02-21 6 views
4

У меня есть две функции:неоднозначный вызов перегруженной функции

void DoSomething(const tchar* apsValue) 
void DoSomething(size_t aiValue) 

Теперь я хочу передать «0» как size_t:

DoSomething(0); 

Компилятор выдает ошибку: «неоднозначный вызов перегруженной функция»

Чтобы решить эту проблему, я могу использовать static_cast, например:

DoSomething(static_cast<size_t>(0)); 

Или просто:

DoSomething(size_t(0)); 

Является ли один из них лучше, чем другие? Существуют ли какие-либо другие подходы к решению этого?

+1

static_cast в любое время лучше, чем в стиле c-style, где это применимо. – iammilind

+3

@iammilind size_t (0) не является литой в стиле c. Он создает новый size_t с '0' как значение –

+0

@iammilind Почему? 'static_cast' предпочтительнее приведения в стиле C, где может возникнуть проблема с тем, какой тип броска стиля C разрешает: для указателей или ссылок. В противном случае ... вы бы напили 'static_cast < MyClass > (42)' или 'MyClass (42)', если вам нужен временный экземпляр 'MyClass'? –

ответ

4

Это неоднозначно, потому что 0 имеет тип int, а не size_t. Он может преобразовать в size_t или указатель, поэтому, если у вас есть перегрузка обоих, , это неоднозначно. В общем, я бы рекомендовал, что если у вас есть перегруженные функции, и один из них может принимать целочисленный тип, вы добавляете перегрузку для int, может быть вдоль линий:

inline void DoSomething(int aiValue) 
{ 
    DoSomething(static_cast<size_t>(aiValue)); 
} 

Интегральные литералов имеют тип int по умолчанию (если они не слишком велики до , вписываются в int), и, предоставляя точное совпадение, вы избегаете неопределенности .

1

Причина двусмысленности: NULL имеет числовое значение 0.

Если в случае, если вы хотите void DoSomething(const tchar* apsValue) при прохождении 0 в качестве параметра, nullptr будет вам полезна. Проверьте What exactly is nullptr?

+0

Но 'NULL' не является причиной двусмысленности в этом вопросе; '0' есть. Новый 'nullptr' здесь не поможет, поскольку в любом случае цель никогда не вызывать версию указателя функции. –

+0

Согласен!Но компилятор находит это неоднозначным, потому что это может быть значение NULL или просто 'int', значение которого равно' 0'. Я попробую перефразировать его. – omggs

1
#include <iostream> 
#include <stddef.h> 
using namespace std; 

void DoSomething(char const* apsValue) { cout << "ptr" << endl; } 
void DoSomething(size_t aiValue) { cout << "int" << endl;} 

template< class Type > Type runtime_value(Type v) { return v; } 
int null() { return 0; } 
template< class Type > Type* nullPointerValue() { return 0; } 

int main() 
{ 
    // Calling the integer argument overload: 
    int dummy = 0; 
    DoSomething(size_t()); 
    DoSomething(runtime_value(0)); 
    DoSomething(null()); 
    DoSomething(dummy); 
    static_cast< void(*)(size_t) >(DoSomething)(0); 

    // Calling the pointer argument overload: 
    DoSomething(nullptr); 
    DoSomething(nullPointerValue<char>()); 
    static_cast< void(*)(char const*) >(DoSomething)(0); 
} 

Это может показаться удивительным, что это работает, но это не только неявное преобразование типа на работе. Кроме того, константа компиляции 0 интегрального типа неявно преобразуется в nullpointer. Например, функция null() позволяет избежать этого, поскольку результат не является постоянной времени компиляции.