Different cast operator called by different compilers

前端 未结 4 1972
深忆病人
深忆病人 2021-02-02 05:15

Consider the following short C++ program:

#include 

class B {
public:
    operator bool() const {
        return false;
    }
};

class B2 : pub         


        
4条回答
  •  执笔经年
    2021-02-02 05:45

    The standard states:

    A conversion function in a derived class does not hide a conversion function in a base class unless the two functions convert to the same type.

    §12.3 [class.conv]

    Which means that operator bool is not hidden by operator int.

    The standard states:

    During overload resolution, the implied object argument is indistinguishable from other arguments.

    §13.3.3.1 [over.match.funcs]

    The "implied object argument" in this case is b, which is of type B2 &. operator bool requires const B2 &, so the compiler will have to add const to b to call operator bool. This -- all other things being equal -- makes operator int a better match.

    The standard states that a static_cast (which the C-style cast is performing in this instance) can convert to a type T (in this case int) if:

    the declaration T t(e); is well-formed, for some invented temporary variable t.

    §5.2.9 [expr.static.cast]

    Therefore the int may be converted to a bool, and a bool may equally be converted to a bool.

    The standard states:

    The conversion functions of S and its base classes are considered. Those non-explicit conversion functions that are not hidden within S and yield type T or a type that can be converted to type T via a standard conversion sequence are candidate functions.

    §13.3.1.5 [over.match.conv]

    So the overload set consists of operator int and operator bool. All other things being equal, operator int is a better match (since you don't have to add constness). Therefore operator int should be selected.

    Note that (perhaps against intuition) the standard does not consider the return type (i.e. the type to which these operators convert) once they have been added to the overload set (as established above), provided the conversion sequence for the arguments of one of them is superior to the conversion sequence for the arguments of the other (which, due to constness, is the case in this instance).

    The standard states:

    Given these definitions, a viable function F1 is defined to be a better function than another viable function F2 if for all arguments i, ICSi(F1) is not a worse conversion sequence than ICSi(F2), and then

    • for some argument j, ICSj(F1) is a better conversion sequence than ICSj(F2), or, if not that,
    • the context is an initialization by user-defined conversion and the standard conversion sequence from the return type of F1 to the destination type (i.e., the type of the entity being initialized) is a better conversion sequence than the standard conversion sequence from the return type of F2 to the destination type.

    §13.3.3 [over.match.best]

    In this case, there is only one argument (the implicit this parameter). The conversion sequence for B2 & => B2 & (to call operator int) is superior to B2 & => const B2 & (to call operator bool), and therefore operator int is selected from the overload set without regard to the fact that it actually doesn't convert directly to bool.

提交回复
热议问题