2015-11-17 4 views
0

У меня есть потоковый базовый класс:оператор потока и контроль приоритета преобразования

class Stream 
{ 
    virtual Stream& operator<< (float num) = 0; 
    virtual Stream& operator<< (double num) = 0; 
    virtual Stream& operator<< (bool val) = 0; 
}; 

И тогда я реализую класс реализации:

class StreamImpl : public Stream 
{ 
    Stream& operator<< (float num ) { ... do stuff ... } 
    Stream& operator<< (double num) { ... do stuff ... } 
    Stream& operator<< (bool val ) { ... do stuff ... } 
}; 

Тогда для новых классов, которые я создаю мой оператор потока, не являющиеся членами функции:

class Blar { }; 

Stream& operator<< (Stream& str, const Blar& blar) { ... do stuff ... } 

Все работает отлично и денди. Но у меня есть проблема, что в некоторых случаях компилятор не знает, какой оператор потока использовать.

Рассмотрим, когда blár имеет оператор произнесения:

class Blar 
{ 
    operator bool() const { return false; } 
}; 

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

void process(Stream& str) 
{ 
    Blar blar; 
    str << blar; 
} 

Так вот проблема компилятор не знает, должен ли он бросить blár bool, а затем использовать член Stream или cast str для ввода Stream и использовать оператор потока, не являющийся членом.

Есть ли способ определить приоритеты приведения?

+1

Сделать 'operator bool()' функцией 'явным'. –

+0

Хороший ответ - и это сработает - но в этом случае я все еще хочу, чтобы неявное преобразование работало. Я бы хотел, чтобы это было более низким приоритетом. –

+0

Это должно сработать. Возможно, это проблема с вашим компилятором. Посмотрите, как он работает на http://ideone.com/GoHnd8. Он также работает под cygwin/g ++ 4.9.3. –

ответ

0

Этот шаблон и SFINAE вещь, мы надеемся устранить неоднозначность (путем определения operator<< для каждого класса, производного от Stream, который удаляет неявное преобразование на левой стороне str << blar):

// the following operator could potentially be defined in the template below, I'm just extending your code 
Stream& operator<< (Stream& str, const Blar& blar) { /* something */ return str; } 

template < 
    typename Str, 
    typename = typename std::enable_if< 
     std::is_base_of<Stream, Str>::value && 
     !std::is_same<Stream, Str>::value 
    >::type 
> 
Stream& operator<< (Str& str, const Blar& blar) { return static_cast<Stream&>(str) << blar; } 

Но, даже мне , он выглядит просто как лишний беспорядок, и он требует рассмотрения - может быть, @R Sahu будет добрым делать это?

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