2016-07-30 10 views
0

У меня есть код, который std::to_string() является переменной, тип которой является параметром шаблона. Предположим, что код:Сделать std :: to_string работать с указателями void нравится operator <<?

template <typename T> 
std::string foo(const T& t) { 
    return std::string("I got ") + std::to_string(t); 
} 

Теперь, иногда этот параметр должен быть void *; и я хотел бы получить адрес в строке, например. "I got 0xdeadbeef". Нет проблем, не так ли? Я должен получить его так же, как если бы я сделал std::cout << my_ptr, правильно? ... К сожалению, для меня это не тот случай. Хорошо,

  • Является ли это «законным» для меня, чтобы код выше работал, как я описал?
  • Кроме настаивают на использовании потока в foo(), есть что-то лучше делать, чем перегрузить std::to_string для void* «с (с использованием std::stringstream в там для operator<<)?

ответ

3
namespace my_to_str { 
    using std::to_string; 
    std::string to_string(void* ptr){ 
    // implement 
    } 
} 

Теперь my_to_str::to_string может быть расширен с собственным набором перегрузками, как void*.

-1

Вы можете сделать заказ operator+ для void * случая:

std::string operator+(const std::string &str, const void *vstr){ 
    return str + std::string(reinterpret_cast<const char *>(vstr)); 
} 
+0

void * не является строкой, я не могу напечатать ее как строку (мне понадобится какая-то функция 'as_hex()' или использовать stringstream); но ваше предложение интереснее, чем это. +1. – einpoklum

+0

'reinterpret_cast' почти наверняка ошибается, и это будет UB. – Barry

+0

@ Барри как? Если 'void * ptr' содержит строку с нулевым завершением, это будет нормально, в другом случае UB будет даже с символом' char * ptr' и без кастинга. – LibertyPaul

1

Вы не можете перегрузить std::to_string() для void*, так что это спорный вопрос.

Но у вас нет есть, чтобы использовать std::to_string(). Вы могли бы реализовать свои собственные, что просто возвращается к использованию stringstream:

namespace N { 
    template <class T> 
    auto to_string(T const& val, int) 
     -> decltype(std::to_string(val)) 
    { 
     return std::to_string(val); 
    } 

    template <class T> 
    std::string to_string(T const& val, ...) 
    { 
     std::ostringstream oss; 
     oss << val; 
     return val.str(); 
    } 

    template <class T> 
    std::string to_string(T const& val) { 
     return to_string(val, 0); 
    } 
} 

И это делает позволяют перегружать N::to_string() с тем, что особенности вы хотите (например, если вы хотите N::to_string(void*) сделать что-то особенное, просто добавьте еще одну перегрузку).

+0

Можете ли вы объяснить, что трюк с 0? Я имею в виду, почему двух перегрузок недостаточно? Кроме того, с каких пор вы можете указать 0 в качестве параметра? – einpoklum

+0

@einpoklum Должно быть, 'int'. Преобразование в 'int' предпочтительнее преобразования в' ... ' – Barry