【问题标题】:C++: reference wrappers and printfC++:引用包装器和 printf
【发布时间】:2016-11-05 15:52:53
【问题描述】:

我有一个 std::vectorstd::reference_wrapper 对象,我想用 printf 打印(不带 cout);现在,如果我写

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

我得到一个无意义的号码(我认为是a的地址);为了获得我的价值,我必须这样做

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

有没有办法在printf 中自动调用.get() 函数(例如,一个不同的% 说明符打印我reference_wrapper content),这样我就可以创建一个通用的函数,它既适用于std::reference_wrapper&lt;type&gt;type?

【问题讨论】:

  • 第一步是使用 iostream 库而不是 stdio 库。
  • 你的第一个代码 sn-p 不会到处编译。 error: cannot pass objects of non-trivially-copyable type 'class std::reference_wrapper&lt;int&gt;' through '...'
  • @Hurkyl 我已经在使用 iostream
  • @ChristianHackl 我编译它没有问题...尝试禁用警告
  • 作为记录,MSVC 也会生成诊断消息:warning C4477: 'printf' : format string '%i' requires an argument of type 'int', but variadic argument 1 has type 'std::reference_wrapper&lt;int&gt;'

标签: c++ reference printf stdvector reference-wrapper


【解决方案1】:

您可能至少要考虑使用 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

【讨论】:

    【解决方案2】:

    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
    

    【讨论】:

      【解决方案3】:

      printf 不进行隐式类型转换,至少在这种情况下不会为您的 std::reference_wrapper 调用转换运算符,要使其正常工作,您需要使用可以进行类型转换的东西,例如 std::cout .

      #include <iostream>                                                             
      
      int a=5;                                                                        
      std::reference_wrapper<int> b=a;                                                
      
      int main() {                                                                                                                           
          std::cout<<b<<std::endl;                                                    
      }
      

      【讨论】:

        猜你喜欢
        • 2021-12-14
        • 1970-01-01
        • 1970-01-01
        • 2015-05-11
        • 2020-10-04
        • 1970-01-01
        • 1970-01-01
        • 2016-09-08
        • 1970-01-01
        相关资源
        最近更新 更多