2016-11-05 9 views
2

У меня есть std::vector из std::reference_wrapper объектов, которые я хочу напечатать с помощью printf (без cout); Теперь, если я пишуC++: справочные обертки и printf

int a=5; 
std::reference_wrapper<int> b=a; 
printf("%i\n\n",b); 

я получаю номер nosense (я думаю, что это адрес a); чтобы получить свое значение я должен сделать

printf("%i\n\n",b.get()); 

Есть ли способ иметь автоматический вызов .get() функции в printf (например, другой % спецификатора, что печать мне reference_wrapper content), так что я могу сделать обобщенную функцию, которая работает как с std::reference_wrapper<type> и type?

+0

Первым шагом будет использование библиотеки iostream, а не библиотеки stdio. – Hurkyl

+0

Ваш первый фрагмент кода не будет компилироваться повсюду. 'error: не может передавать объекты нетривиально-скопируемого типа 'class std :: reference_wrapper ' through '...'' –

+0

@Hurkyl Я уже использую iostream – volperossa

ответ

2

Вы, вероятно, хотите по крайней мере, подумайте об использовании библиотеки C++ IO вместо устаревших функций C. Это, как говорится, вы можете написать обертку вокруг printf обеспечить развёртки эталонных оберток:

template<typename... Params> 
void my_printf(char const* fmt, Params&&... ps) 
{ 
    printf(fmt, unwrap(std::forward<Params>(ps))...); 
} 

с unwrap реализуется следующим образом:

template<typename T> 
decltype(auto) unwrap_impl(T&& t, std::false_type){ 
    return std::forward<T>(t); 
} 

template<typename T> 
decltype(auto) unwrap_impl(T&& t, std::true_type){ 
    return t.get(); 
} 

template<typename T> 
decltype(auto) unwrap(T&& t) 
{ 
    return unwrap_impl(std::forward<T>(t), is_reference_wrapper<std::decay_t<T>>{}); 
} 

и is_reference_wrapper черты:

template<typename T> 
struct is_reference_wrapper : std::false_type {}; 

template<typename T> 
struct is_reference_wrapper<std::reference_wrapper<T>> : std::true_type{}; 

demo

1

printf() - это функция библиотеки C, которая абсолютно ничего не знает о классах и ссылках на C++ и никогда ничего не узнает о них.

C++ имеет свой собственный вход/выход библиотека, которая использует поток объектов, который знает о C++ классов, и как использовать их:

#include <iostream> 

#include <memory> 

int main() 
{ 
    int a=5; 
    std::reference_wrapper<int> b=a; 

    std::cout << b << std::endl; 

    return 0; 
} 

Выход:

5 
1

printf не выполняет неявное преобразование типа, по крайней мере, не вызывает оператор преобразования в этом случае для вашего std :: reference_wrapper, чтобы заставить его работать, вам нужно использовать что-то, что может преобразовывать тип, например std::cout.

#include <iostream>                

int a=5;                   
std::reference_wrapper<int> b=a;             

int main() {                               
    std::cout<<b<<std::endl;              
}