调用printf时隐式转换为char*

Ziv*_*ivS 4 c++ printf gcc variadic-functions c++11

我在我的C++ GUI应用程序中使用Unicode字符串作为图标,并希望摆脱u8"\uf118"我所散布的所有魔术字符串,并且在途中,使这些字符串成为他们自己的类型.

所以我创建了一个这样的类:

struct icon
{
    explicit constexpr icon(const char (&unicode_icon)[4]) :
        _icon{ unicode_icon[0], unicode_icon[1], unicode_icon[2], unicode_icon[3] }
    {
    }
    operator const char*() const
    {
        return _icon.data();
    }
private:
    std::array<char, 5> _icon;
};
Run Code Online (Sandbox Code Playgroud)

GUI库使用某种形式printf(我认为vfprintf)所以代码调用:

icon smiley { u8"\uf118" };
printf("%s", smiley);
Run Code Online (Sandbox Code Playgroud)

我到目前为止在Windows上对此进行测试并且效果很好,但是当我使用gcc(5.1)在Linux上编译它时,我收到以下警告:

main.cpp:22:24: warning: format '%s' expects argument of type 'char*', but argument 2 has type 'icon' [-Wformat=]
     printf("%s", smiley);
Run Code Online (Sandbox Code Playgroud)

这里有实例

当我运行它时,我在内部遇到了一个seg故障,vfprintf因为它没有使用我提供的强制转换运算符.

我知道当我将图标传递给GUI库时,我可以显式地转换图标(它有以下原型,(const char* fmt, ...)但这会让我写更多的代码,而且,它看起来会更糟.

有没有办法让编译器发挥魔力并允许我像这样调用函数:( printf("%s", smiley);或其他一些简单的方法)?

Som*_*ude 5

C++没有很好地处理Varargs函数.最重要的是,没有隐式的对象转换,因为编译器不能(在一般情况下)知道实际期望的类型.

如果有替代方案,最好的解决方案是使用vararg函数.对于printf和朋友有(对于printfstd::cout).

如果由于某种原因仍然需要使用vararg函数(例如,因为您使用C库),那么唯一的解决方案是显式地转换对象.在你的情况下,它会static_cast<const char*>(smiley).

  • 另一个变体是有一个`c_str()`成员(如`std :: string`那样). (3认同)