转换重载函数是不明确的

use*_*413 6 c++ gcc overloading function-pointers type-conversion

我有一个问题,即创建函数指针编译错误重载函数结果对于g ++ 4.7和g ++ 4.8但不在克++ 4.4,G ++ 4.6或铛++ 3.2(以及可能VS2010).

谷歌搜索了一下是为了解问问题是用g ++还是我的代码,我还是无法决定.适用于函数指针转换的重载决策规则是否不同于适用于函数调用的规则?

这是一个稍微最小化的代码,用于演示此问题:

template < class T >
struct Dummy {
    typedef T value_type;
    value_type value;
};

template < class T >
typename T::value_type f (const T& x) {
    return x.value;
}

template < class T >
T f (Dummy< T > const& x) {
    return x.value + 1;
}

int main (int, char**) {
    Dummy< int > d = { 1 };
    // No ambiguity here
    d.value = f(d);
    // This is ambiguous for *some* compilers
    int (* const f_ptr)(Dummy< int > const&) = f;
    return f_ptr( d );
}
Run Code Online (Sandbox Code Playgroud)

clang ++ 3.2,g ++ 4.4和g ++ 4.6在-Wall -pedantic --std=c++98没有警告的情况下编译它.

但是,g ++ 4.7和g ++ 4.8会出现以下错误消息:

test.cc: In function ‘int main(int, char**)’:
test.cc:15:45: error: converting overloaded function ‘f’ to type ‘int (* const)(const struct Dummy<int>&)’ is ambiguous
test.cc:6:18: error: candidates are: typename T::Type f(const T&) [with T = Dummy<int>; typename T::Type = int]
test.cc:9:3: error:                 T f(const Dummy<T>&) [with T = int]
Run Code Online (Sandbox Code Playgroud)

这是新版本的g ++的问题还是我的代码实际上是错的?

如果是的话,怎么会解决这种模棱两可的问题呢?

Cas*_*eri 3

这是新版本 g++ 的问题还是我的代码实际上是错误的?

我想这是合法的代码(但我不太确定)。添加到列表中:它确实使用 clang 3.3 和 icc 13.1.3 进行编译。

如何解决这一含糊不清的问题?

您可以使用

    int (* const f_ptr)(Dummy< int > const&) = f<int>;
Run Code Online (Sandbox Code Playgroud)

选择第二个过载或

    int (* const f_ptr)(Dummy< int > const&) = f<Dummy<int> >;
Run Code Online (Sandbox Code Playgroud)

选择第一个。

如果您不想手动消除歧义(就像我上面的建议一样),我可以建议一种使用 SFINAE 消除歧义的解决方法。我假设您可以使用 C++11(函数模板的默认模板参数),但我相信通过一些额外的工作它可以扩展到 C++98。

将 的定义更改f为:

template < class T, class R = typename T::value_type>
R f (const T&) {
    return x.value;
}

template < class T, class R = T>
R f (Dummy< T > const&) {
    return x.value + 1;
}
Run Code Online (Sandbox Code Playgroud)

这样,原始行(如下)在 gcc 中可以正常编译(4.7.3 和 4.8.1):

int (* const f_ptr)(Dummy< int > const&) = f;
Run Code Online (Sandbox Code Playgroud)