为什么这个函数重载参数类型转换模糊不清?

时间:2014-11-14 15:09:35

标签: c++ implicit-conversion overloading

有人能解释一下这个函数的重载决策是不明确的吗?

假设:

/// This type *contains* a @c T.
template< typename T >
class User_Type
{
public:
    /// This <em>conversion constructor</em> is a key part of it's API;
    ///   it won't likely change.
    User_Type( T const & ar_data )
      : m_data( ar_data )
    {}
private:
    T m_data;
};

/// @c some_value is just a templated function that generates a @c T.
template< typename T > T some_value();
template<> char some_value();
template<> int some_value();

/// This overloaded, non-templated function represents some third-party
///   code somewhere else; it's API can't be changed.
void other_function( User_Type< char > const& );
void other_function( User_Type< int > const& );

/// This is user-code.  It's contents exercise some aspect of the 'User_Type' API.
///   This code can change.
template< typename T >
void function()
{
    other_function( some_value< T >() ); /* AMBIGUOUS CALL */

    User_Type< T > user_var = some_value< T >(); /* UNAMBIGUOUS CONVERSION */
    other_function( user_var ); /* UNAMBIGUOUS CALL */
}
template void function< char >();
template void function< int >();

并使用g++-4.9 -Wall -Wextra进行编译,我收到以下错误:

In instantiation of ‘void function() [with T = char]’:
    error: call of overloaded ‘other_function(char)’ is ambiguous
    note: candidates are:
    note: void other_function(const User_Type<char>&)
    note: void other_function(const User_Type<int>&)
In instantiation of ‘void function() [with T = int]’:
    error: call of overloaded ‘other_function(int)’ is ambiguous
    note: candidates are:
    note: void other_function(const User_Type<char>&)
    note: void other_function(const User_Type<int>&)

我希望other_function( char )的最佳匹配为other_function( User_Type< char > const& )other_function( int )的最佳匹配为other_function( User_Type< int > const& )

我知道必须为other_function的每个参数进行类型转换。我希望char User_Type< char >成为charUser_Type< int >的更好选择,char允许int int促销。我希望User_Type< int > int成为User_type< char >int的更好选择,char允许User_Type< T > user_var T }转换。

此外,如果我从other_function( user_var )创建本地{{1}},那么我可以毫不含糊地呼叫{{1}}。从语义上讲,这应该等同于第一个原始陈述。

2 个答案:

答案 0 :(得分:2)

由于other_function(char)other_function(int)没有完全匹配,

other_function( some_value< T >() );

必须隐式转换其参数以匹配以下内容之一:

void other_function( User_Type< char > const& );
void other_function( User_Type< int > const& );

但是User_Type<char>有ctor User_Type<char>( char const& ),它接受​​intUser_Type<int>有ctor User_Type<int>( int const& ),接受char

您的转化次数属于&#34;用户定义的转化顺序&#34;由于这两种转换都是可能的,因此两者都包含在具有相同排名的重载集中。因此,电话是模棱两可的。 (有关详细信息,请参阅标准中的13.3.3.2 排名隐式转换序列。)

答案 1 :(得分:1)

我认为这里的问题是尝试根据符合条件的转化选择过载。我可以取出一些模板并获得相同的结果:

class User_Type_char
{
public:
    User_Type_char(char const &) {}
};

class User_Type_int
{
public:
    User_Type_int(int const &) {}
};

void other_function( User_Type_char const& );
void other_function( User_Type_int const& );

template< typename T >
void function()
{
    other_function( 'a' ); /* AMBIGUOUS CALL */
}

问题是过载列表中没有完美的匹配,所以我们开始检查转换。反过来,charint可以进行隐式转换,因此不清楚您想要哪一个。

如果对于相同的代码我更改了第一个类的构造函数

class User_Type_char
{
public:
    User_Type_char(const char*) {}
};

现在,同一个调用变得明确,并调用User_Type_int版本。