在clang中强制使用`const char[]`字符串字面量

10

编译以下代码

void f(char *, const char *, ...) {}
void f(const char *, ...) {}

int main()
{
    f("a", "b");
}

使用clang时,我遇到了这个错误:

prog.cpp:6:2: error: call to 'f' is ambiguous
        f("a", "b");
        ^
prog.cpp:1:6: note: candidate function
void f(char *, const char *, ...) {}
     ^
prog.cpp:2:6: note: candidate function
void f(const char *, ...) {}
     ^
据我所知,在C++中,字符串字面量是常量,因此重载规则应该将第一个变量从考虑中排除,从而明确解决为第二个变量。但我猜Clang会将它们设置为非const以实现兼容性(我知道MSVC也这样做)。 使用哪些编译器标志来修复这个问题?我已经使用了-std=c++11进行编译。 编辑:显式转换为const char* 可以解决这个问题:
    f((const char*)"a", "b");

但如果我的看法正确,观察到的编译器行为并不符合标准,我希望修复编译器行为而不是符合标准的代码。


1
@Jarod42:因为我喜欢这个名字。如果代码没有问题,我不认为“修复”它是正确的解决方案。 - Yakov Galka
1
我曾经搜索过编译器开关以停用这种可怕的转换为char*,但是没有找到任何一个。至少,没有记录在案的。是时候添加一个了,我猜?顺便提一下,MSVC有一些“严格字符串”开关。 - dyp
1
哈哈,我刚刚想到了完全相同的MCVE(最小可重现示例),一个字不差...吹毛求疵的头脑想得一样啊 ;) - M.M
1
@davmac 如果允许转换为 char *,那么会存在歧义。 - M.M
1
@davmac 不,我之前曾经看到过这种诊断信息,与涉及添加“const”的转换序列有关。 - M.M
显示剩余16条评论
1个回答

5

我认为这是一个bug。在C++11中,将字符串字面量转换为char *已被删除,并且我不知道涉及它的转换序列的重载解析中是否有任何规定。

作为一种解决方法,不需要更改每个对f的调用,您可以编写另一个重载函数,通过引用捕获数组来显式捕获每个使用字符串字面量的调用:

template<size_t N, typename ...F>
void f(char const (&a)[N], F&&... args)
{
    f((char const *)a, std::forward<F>(args)...);
}

很遗憾现在 [[gnu::format(printf, 1, 2)]] 不起作用了 :( - Yakov Galka
这是正确的答案!根据标准:窄字符串字面值的类型为“n个const char的数组”。 - Jeffery Thomas
@ybungalobill 哎呀,也许有另一种方法可以让你继续使用它。 - M.M

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接