2013-08-09 4 views
1
class Test { 
public: 
    operator string() { 
     return string{"TEST!"}; 
    } 
}; 

int main() { 
    cout << Test{}; 
} 

Я ожидал, что тестовый объект будет неявно преобразуются в строку и выход, но он дает мне ошибку:неявного преобразования типа не работает

error: cannot bind 'std::ostream {aka std::basic_ostream<char>}' lvalue to 'std::basic_ostream<char>&&' 

Это явное преобразование работает:

cout << string{Test{}}; 

Я получил это работает литьем в const char*:

class Test { 
public: 
    operator const char*() { 
     return "TEST!"; 
    } 
}; 

Тогда выход:

cout << Test{}; //Yay it works. 

Я предполагаю, что cout << string уже неявное преобразование из string в char * и если я использую литье в строку, она не будет выполнять преобразование в два уровня из Test to string to char *. После прямого литья до const char* он работает. (Пожалуйста, исправьте, если предположение неверно)


ДОКАЗАТЬ это предположение верно

class Test { 
public: 
    operator string() { 
     return string{"TEST!"}; 
    } 
}; 

ostream& operator<< (ostream& os, string s){ 
    os << s; 
    return os; 
} 

Это будет выполнять прямой вычет типа из Test to string и строки вывода. и после того, как я попробовал, он работает!

cout << Test{}; //YAY WORKS! OUTPUT "TEST!" 

Что-то особенное cout << string объясняется Borgleader. Предположение частично правильно и частично ошибочно.

+0

У вас есть свои определения явного и неявного переключения. 'T {x}' * явно * указывает 'T', просто' x' в одиночку этого не делает. Ваша первая строка будет * неявно * конвертировать в строку. – GManNickG

+0

@GManNickG да, они меня всегда путают .. Отредактировано. – texasbruce

+0

Это должно помочь вам: http://stackoverflow.com/questions/17539555/why-does-outputting-a-class-with-a-conversion-operator-not-work-for-stdstring – chris

ответ

4

Ключевое слово explicit означает, что вы должны явно сделать преобразование самостоятельно, как std::string(Test{}). Он отключает неявные преобразования.

cout << string{Test{}}; // <-- this is explicit, you've got implicit and explicit confused 

Правило заключается в том, что при выводе аргумента шаблона не учитывается определенное пользователем преобразование. Однако, как вы заметили, если у вас есть только оператор преобразования для int, он компилируется. Это связано с тем, что эта перегрузка не является шаблоном функции. Посмотрите на reference page, и вы увидите:

basic_ostream& operator<<(int value); 

Это не-шаблонные перегрузки поэтому компилятор будет искать преобразования определенного пользователя.

+0

явный и неявный всегда меня путают ... Я удалил ключевое слово '' явное '', но все равно та же ошибка. Я не думаю, что есть ключевое слово 'implicit'? – texasbruce

+2

@texasbruce: Нет, 'implicit' неявно. ;) – GManNickG

+0

Не могли бы вы взглянуть на мое редактирование? Я удалил ключевое слово и он все еще не работает ... – texasbruce

2

Перегрузка std::string (или std::basic_string) является функциональным шаблоном. Определенные пользователем преобразования не учитываются при выводе аргумента шаблона, поэтому компилятор не считает перегрузку string совпадением.

Чтобы избежать ошибки, определите перегрузку basic_ostream& operator<<(basic_ostream&, Test&) для вашего класса.

+0

Можете ли вы объяснить, почему объект Test неявно преобразован в строку? – texasbruce

+1

@texasbruce, Этот ответ, его другой комментарий и связанный обман все это делают. – chris

+0

Ничего себе! Эффективный C++ говорит, что неявные функции преобразования типа являются ___never___, рассмотренными при выводе аргумента шаблона. –

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