2016-12-20 3 views
1

Следующий код:Использование перегруженного оператора неоднозначным

typedef void HELPER; 

const HELPER* helper = _helper; 

inline ostream& operator <<(ostream& out, const HELPER* arg) 
{ out << (const char*)(arg); return out; } 

взрывает если попытаться

cout << helper; 

В частности, я получаю:

main.cpp:35:28: error: use of overloaded operator '<<' is ambiguous (with operand types 'basic_ostream >' and 'const HELPER *' (aka 'const void *'))

и перечисляет несколько кандидатов :

/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/ostream:207:0: note: candidate function 
    basic_ostream& operator<<(const void* __p); 
       ^
main.cpp:25:17: note: candidate function 
inline ostream& operator <<(ostream& out, const HELPER* arg) 
       ^
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/ostream:195:20: note: candidate function 
    basic_ostream& operator<<(bool __n); 
       ^

Я немного удивлен, что мой typedef не вызывает более сильного типа, соответствующего здесь. Как я могу запустить эту перегрузку оператора?

EDIT: Дальнейшее разъяснение, цель этого кода заключается в том, что я настроен с двойным таргетингом на набор библиотек Arduino. Они управляют своими строками часто с:

typedef void __FlashStringHelper; 

void showHelp(const __FlashStringHelper* helpText) 
{ 
    Serial.print(helpText); 
} 

Я iostream и планировал на этой двойной цели нравится, поэтому я перегружен < < на Последовательная объекта и сделал предыдущий в (это упрощенно версия, например)

#define cout Serial 

void showHelp(const __FlashStringHelper* helpText) 
{ 
    cout << helpText; 
} 

Теперь я хочу на самом деле нацелиться на реальный iostream для другой арки, но старый код Arduino не может сильно отличаться от его __FlashStringHelpers. Вот где я в

+5

Ваш символ 'HELPER' в основном только * псевдоним * для' void'. Таким образом, у вас есть две перегрузки для 'const void *' (ваш и стандарт) плюс эти указатели могут быть неявно преобразованы в 'bool', что дает вам третью альтернативу. –

+5

typedef не вводит новый тип. – Danh

+5

И какова * актуальная * проблема, которую вы хотите решить с помощью предлагаемого вами решения? Почему вы сделали такую ​​перегрузку? В чем его цель?Может быть, мы сможем помочь вам в этом? См. Некоторые связанные чтения о [проблема XY] (http://xyproblem.info/). –

ответ

2

typedef не создавать типы это псевдонимы их,

inline ostream& operator <<(ostream& out, const HELPER* arg) 

эквивалентно

inline ostream& operator <<(ostream& out, const void* arg) 

Может быть, вы хотите создать тип с именем ХЕЛПЕР

class HELPER{}; 
+0

Могу также упомянуть, что вы не можете перегружать встроенные типы – NathanOliver

+0

Какой тип оператор << принадлежит к тому, что ОП переопределяет? https://msdn.microsoft.com/en-us/library/1z2f6c2k.aspx –

0

Как Zekian ответил на ваш вопрос, это вот что может пригодиться вам или помочь вам достигните того, что вы пытаетесь сделать.

#include <iostream> 

template <class T> 
class Helper { 
private: 
    T obj_; 

public: 
    explicit Helper<T>(T obj) : obj_(obj) {} 

public: 
    T getObj() const { return obj_; } 
    void setObj(T obj) { obj_ = obj; }   

    template<class U> 
    inline friend std::ostream& operator<< (std::ostream& out, const Helper<U>& rhs); 
}; 

template<class U> 
std::ostream& operator<< (std::ostream& out, const Helper<U>& rhs) { 
    return out << rhs.obj_; 
} 

int main() { 
    Helper<int> helper(3); 
    std::cout << helper << std::endl; 
    return 0; 
} 

Это шаблон класса обертка с перегруженной ostream оператора < <. Это будет работать для интегральных и атомных типов. Если вы передадите другой объект структуры или класса, вам придется определить для них другие перегруженные операторы.

Пример - Шаблон того же класса, но на этот раз с использованием класса или структуры.

#include <iostream> 

template <class T> 
class Helper { 
private: 
    T obj_; 

public: 
    explicit Helper<T>(T obj) : obj_(obj) {} 

public: 
    T getObj() const { return obj_; } 
    void setObj(T obj) { obj_ = obj; } 

    template<class U> 
    inline friend std::ostream& operator<< (std::ostream& out, const Helper<U>& rhs); 
}; 

template<class U> 
std::ostream& operator<< (std::ostream& out, const Helper<U>& rhs) { 
    return out << rhs.obj_; 
} 

struct Staff { 
    int employees = 4; // Default to 4 
}; 

int main() { 
    Staff staff; 
    Helper<Staff> helper(staff); 
    std::cout << helper << std::endl; // will not compile 

    return 0; 
} 

Чтобы исправить эту ostream потребуется перегруженный оператор для объекта персонала

template <class T> 
class Helper { 
private: 
    T obj_; 

public: 
    explicit Helper<T>(T obj) : obj_(obj) {} 

public: 
    T getObj() const { return obj_; } 
    void setObj(T obj) { obj_ = obj; } 

    template<class U> 
    inline friend std::ostream& operator<< (std::ostream& out, const Helper<U>& rhs); 
}; 

template<class U> 
std::ostream& operator<< (std::ostream& out, const Helper<U>& rhs) { 
    return out << rhs.obj_; 
} 

struct Staff { 
    int employees = 4; 

    inline friend std::ostream& operator<< (std::ostream& out, const Staff& rhs); 
}; 

std::ostream& operator<<(std::ostream& out, const Staff& rhs) { 
    return out << rhs.employees; 
} 

int main() { 

    Staff staff; 
    Helper<Staff> helper(staff); // Default to 4 
    std::cout << helper << std::endl; // Will Print 4 
    // To Change Staff's Employee count for the helper wrapper do this: 
    staff.employees = 12; // Change To 12 
    helper.setObj(staff); // pass the changed struct back into helper 
    std::cout << helper3 << std::endl; // Will Now Print 12 

    // And For Other Default Types 
    Helper<int> helper2(3); 
    std::cout << helper2 << std::endl; 

    Helper<float> helper3(2.4f); 
    std::cout << helper3 << std::endl; 

    return 0; 
} 
Смежные вопросы