2013-12-25 3 views
0

У меня есть класс строк:Понимание метода перегрузки правила

#include <stdint.h> 

class CString { 
public: 
    CString() {} 
    explicit CString(uint64_t ui64, int width = -1, int base = 10, char fillChar = ' ') {} 
    CString(const char * str) {} 

    CString arg(const CString& argument) const {return CString();} 

    template <typename T> 
    inline CString arg(T argument, int width = -1, int base = 10, char fillChar = ' ') const 
    { 
     return arg(CString(argument, width, base, fillChar)); 
    } 
}; 

Теперь я использую этот класс:

void main() 
{ 
    CString str; 
    str.arg("123"); 
} 

И получаю ошибку:

error C2665: 'CString::CString' : none of the 4 overloads could convert all the argument types 
1>   source.cpp(6): could be 'CString::CString(uint64_t,int,int,char)' 
1>   while trying to match the argument list '(const char *, int, int, char)' 
1>   source.cpp(22) : see reference to function template instantiation 'CString CString::arg<const char*>(T,int,int,char) const' being compiled 
1>   with 
1>   [ 
1>    T=const char * 
1>   ] 

Почему Безразлично 't arg(CString&) вызывается, используя конструктор CString(const char *)?

+0

Ваша версия шаблона 'arg()' требует, чтобы по крайней мере два аргумента были invokable, но вы передаете один. – Nawaz

+0

@Nawaz: спасибо, исправлено и отредактировано вопрос (до сих пор не компилируется). –

ответ

1

Когда вы звоните

str.arg("123"); 

лучший матч получается с помощью шаблона функции arg, поскольку CString arg(const CString& argument) требует преобразования в определенный пользователем тип. Шаблон функции затем вызывает

return arg(CString(argument, width, base, fillChar)); 

но нет CString конструктора, который совпадает со списком аргументов const char*, int, int, char, что вы проходящими здесь.

Невозможно позвонить по номеру CString(uint64_t, int, int, char), потому что преобразование с const char* в uint64_t является неверным преобразованием. Этот упрощенный пример кода показывает ту же проблему:

#include <cstdint> 
void foo(std::uint64_t) {} 

int main() 
{ 
    foo("hello"); 
} 

error: invalid conversion from 'const char*' to 'uint64_t {aka long long unsigned int}' [-fpermissive]

foo("hello");

Если вы закомментировать шаблон функции члена arg, то CString arg(const CString& argument) будет называться, с помощью неявного преобразования из const char* в CString.

+0

Я понимаю это.Мой вопрос: «Почему не вызывается' arg (CString &) ', используя конструктор' CString (const char *)? –

+0

@ VioletGiraffe, потому что шаблон 'arg' может обеспечить лучшее совпадение, тогда как' CString arg (const CString &) 'требует определенного пользователем преобразования. Если вы закомментируете шаблон 'arg', код будет компилироваться в порядке. Я могу ответить на этот вопрос. – juanchopanza

+0

Является ли перегрузка совпадением всегда выполняемой 1 шаг за раз? Если компилятор мог видеть 2 шага вперед, было бы ясно, что функция 'arg' шаблона является плохим. –

3

Примечание: Это отвечает на исходный вопрос, прежде чем он был изменен на другой.

why doesn't template arg overload work?

Поскольку для этого требуется не менее двух аргументов, и вы передаете один.

template <typename T> 
inline CString arg(T argument, int width, int base = 10, char fillChar = ' ') 
{ ... } 
+0

Я слепой! Спасибо. –

+0

Он все еще не компилируется. 'ошибка C2665: CString :: CString ': ни одна из перегрузок не может преобразовать все типы аргументов' –

+0

@VioletGiraffe Я не могу воспроизвести это, но у меня нет VS. Не могли бы вы опубликовать [SSCCE] (http://sscce.org/), используя стандартный C++? – juanchopanza

Смежные вопросы