问题 隐式转换运算符优先级


在下面的代码中(住在coliru):

#include <iostream>
#include <string>

int main()
{
    struct S {
        operator bool        () const { return false; }
        operator std::string () const { return "false"; }
    } s;
    std::cout << s << "\n"; // outputs 0
}

怎么编译 选择 选择隐式转换为 bool 过度 std::string

我的假设是,在这种情况下,它可能纯粹是宣称不同口味的顺序 std::basic_ostream::operator<<,但这一切?标准是否说明了选择特定的隐式转换?


5355
2018-02-15 14:25


起源

只是为了挑剔,没有任何东西是暗示性的。类型是隐式转换的,但是a 投 手段 显式转换。 - StoryTeller
@StoryTeller谢谢,知道具体的术语很好。我编辑了我的问题。 - YSC


答案:


回想起那个 std::string 它不是一个独立的类型,它实际上是一个类模板专业化 - std::basic_string<char>。非常重要的细节是流式传输的潜在过载 std::string 不接受 std::string const& 论证,它是一个 功能模板 推断出一个 std::basic_string const&

template <class CharT, class Traits, class Allocator>
std::basic_ostream<CharT, Traits>& 
    operator<<(std::basic_ostream<CharT, Traits>& os, 
               const std::basic_string<CharT, Traits, Allocator>& str);

模板演绎 从不考虑转换。名称查找将找到此功能模板,然后由于扣减失败而丢弃为不可行。 S 不是一个 basic_string<CharT, Traits, Allocator> 对于任何这样的类型,我们已经完成了。唯一可行的流运营商将是所有不可或缺的流运营商 bool 是最好的比赛。

如果特别是带签名的函数:

std::ostream& operator<<(std::ostream&, std::string const& );    

然后调用将是模糊的 - 您将获得两个等效排名的用户定义转换。


通过使用我们自己的函数而不是百万次重载,这很容易验证 operator<<

void foo(bool ); // #1
void foo(std::string ); // #2

void bar(bool );  // #3
template <class C, class T, class A>
void bar(std::basic_string<C,T,A> ); // #4

foo(S{}); // error: ambiguous
bar(S{}); // calls #3

11
2018-02-15 15:05



@YSC:我已经编辑过我来纠正它。我当时没有意识到它现在是巴里的不完美版本。我还是离开了,因为我认为“不要这样做,那么”建议很有用。 - Martin Bonner
@Barry,演绎成功为模板运算符<<。编译器选择成员函数,因为它不是模板。看到我的回答。 - Oliv
一个明确的方法来看待这个OP是评论出来 operator bool 从原始代码...然后它无法编译(它不会调用字符串转换器) - M.M
@ M.M是的,那也行得通。 - Barry


ostream& operator<<( bool value );

是会员的职能 std::ostream。另一方面:

std::ostream& operator<<(std::ostream& os, const std::string& str);

是一个独立的功能 - 它实际上被声明为模板。参考 S 与任何模板都不匹配 - 因此不考虑模板扩展。


可以唯一地确定应选择哪个过载,但我建议您不要这样做。

a)这始终是标准中棘手的一个角落(因此您可能会遇到编译器错误;

b)未来的开发人员总会发现难以阅读的代码。

我的建议是完全避免这个问题,只需要明确转换运算符,或者给它们命名 to_bool() 和 to_string()


2
2018-02-15 14:37



会员/非会员无关紧要。这就是模板性问题。 - T.C.
我同意你的结论(更喜欢明确的转换),但我对你的解释并不确定。看到 coliru上的这个例子。 - YSC
@ T.C。啊,哈!谢谢。 - Martin Bonner