2

I have a std::vector of std::reference_wrapper objects that I want to print with printf (without cout); now, if I write

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

I get a nosense number (I think is the address of a); to obtain my value I have to do

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

Is there a way to have automatic call to .get() function in printf (e.g. a different % specificator that print me the reference_wrapper content) so I can make a generalized function that works both with std::reference_wrapper<type> and type?

volperossa
  • 1,339
  • 20
  • 33
  • The first step would be to use the iostream library rather than the stdio library. –  Nov 05 '16 at 15:58
  • Your first code snippet won't compile everywhere. `error: cannot pass objects of non-trivially-copyable type 'class std::reference_wrapper' through '...'` – Christian Hackl Nov 05 '16 at 16:00
  • @Hurkyl I already use iostream – volperossa Nov 05 '16 at 16:08
  • @ChristianHackl I compile it without problems...try disabling warnings – volperossa Nov 05 '16 at 16:10
  • @volperossa: Why would disabling warnings prevent an error? Why would I shut up the compiler which protests when you ask it to create an executable with undefined behaviour in it? Anyway, it produces this error with GCC 4.9.2, regardless of the warning level. – Christian Hackl Nov 05 '16 at 16:15
  • @volperossa: You're not using iostream in this code example: you're using stdio. –  Nov 05 '16 at 16:15
  • 1
    For the record, MSVC produces a diagnostic message as well: `warning C4477: 'printf' : format string '%i' requires an argument of type 'int', but variadic argument 1 has type 'std::reference_wrapper'` – Christian Hackl Nov 05 '16 at 16:18
  • @ChristianHackl "Why would disabling warnings prevent an error? Why would I shut up the compiler which protests when you ask it to create an executable with undefined behaviour in it?" just for testing and understanding the behavior :) – volperossa Nov 05 '16 at 18:00

3 Answers3

2

printf() is a C library function that knows absolutely nothing about C++ classes and references, and will never know anything about them.

C++ has its own input/output library, that uses stream objects, that knows about C++ classes, and how to use them:

#include <iostream>

#include <memory>

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

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

    return 0;
}

Output:

5
Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
2

You probably want to at least consider using a C++ IO library instead of legacy C functions. That being said, you can write a wrapper around printf to provide unwrapping of reference wrappers:

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

with unwrap implemented as follows:

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>>{});
}

and the is_reference_wrapper trait:

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

krzaq
  • 16,240
  • 4
  • 46
  • 61
1

printf doesn't do implicit type conversion, at least not calling the conversion operator in this case for your std::reference_wrapper, to make it work you need to use something that can do type conversion, like std::cout.

#include <iostream>                                                             

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

int main() {                                                                                                                           
    std::cout<<b<<std::endl;                                                    
}
swang
  • 5,157
  • 5
  • 33
  • 55