调用printf时隐式转换为char *

时间:2018-01-04 08:57:57

标签: c++ c++11 gcc printf variadic-functions

我在我的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;
};

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

icon smiley { u8"\uf118" };
printf("%s", smiley);

到目前为止,我在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);

Live example here

当我运行它时,我在vfprintf内部出现了一个seg错误,因为它没有使用我提供的强制转换运算符。

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

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

1 个答案:

答案 0 :(得分:5)

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

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

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