2015-03-30 2 views
1

У меня есть следующий код ...Вызывающего специализировано ostream оператор

#include <sstream> 

enum class eTag 
{ 
    A, 
    B, 
    C 
}; 

template<eTag I> std::ostream& operator<< (std::ostream& str, int i) 
{ 
    return str; // do nothing 
} 

template<> std::ostream& operator<< <eTag::A>(std::ostream& str, int i) 
{ 
    return str << "A:" << i; // specialize for eTag::A 
} 

template<> std::ostream& operator<< <eTag::B>(std::ostream& str, int i) 
{ 
    return str << "B:" << i; // specialize for eTag::B 
} 

template<> std::ostream& operator<< <eTag::C>(std::ostream& str, int i) 
{ 
    return str << "C:" << i; // specialize for eTag::C 
} 

int main() 
{ 
    std::ostringstream s; 

    // s << <eTag::A>(42) << std::endl; 

    return 0; 
} 

компилируется. Но, как вы можете видеть из прокомментированной строки в main(), я боюсь, как фактически вызывать специализацию оператора ostream.

+0

возможно дубликат [Является ли это невозможно вызвать операторов C++ вручную?] (http://stackoverflow.com/questions/7225962/is-it-not-possible-to-call-c-operators-manually) – Pradhan

+1

Хотя отвратительный, 'operator << (std :: cout, 42) << std :: endl; '. Мне любопытно, почему ты хочешь это сделать. ' – WhozCraig

+1

@Pradhan не совсем обман, не так ли? Поскольку связанный с вами вопрос в основном говорит о перегрузке «operator +» для основных типов. – vsoftco

ответ

1

Быстрый ответ:

operator<< <eTag::A>(std::cout,42); 

Я думаю, что вы гораздо лучше с реализации собственного шаблона класса манипулятором, что друзья ostream& operator<<(ostream&), и сохраняет состояние как переменную (инициализируется с помощью конструктора). См here (для матричной части, за исключением)

1
operator<<<eTag::A>(std::cout, 42) << std::endl; 

(Вы можете добавить пробел между operator<< и список аргументов шаблона, если вы хотите. Не имеет значение.)

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

inline std::ostream& operator<<(std::ostream& os, eTag x) { 
    if (x == eTag::A) { 
     return os << "A:"; 
    } else if (x == eTag::B) { 
     return os << "B:"; 
    } else if (x == eTag::C) { 
     return os << "C:"; 
    } else { 
     throw std::range_error("Out of range value for eTag"); 
    } 
} 

Тогда:

std::cout << eTag::A << 42 << std::endl; 

A good compiler will be able to inline this, так что ваш код будет столь же эффективно, как если бы вы только что ввели

std::cout << "A:" << 42 << std::endl; 
+0

приятно, единственная проблема, которую я вижу здесь, это тот факт, что 'throw' никогда не будет выполняться. Если вы передаете что-либо еще, кроме тега, то запускается оператор 'std'' <<. Я вижу, это может произойти, если у вас есть более крупное' enum' ... – vsoftco

+0

@vsoftco Вы можете думать об этом как о страже в случае, если кто-то добавляет больше тегов в перечисление и забывает обновить 'operator <<'. – Brian

+0

Действительно, хороший момент! – vsoftco

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