6

为什么我的编译器会将以下 GetLength 函数指针视为模棱两可
的伪代码:

size_t GetLength(char*);
size_t GetLength(wchar_t*);
struct ITEM { };
double GetLength(ITEM*);

CString GetInfo(ITEM * item, std::function<double (ITEM*)> fn)
{
  ... omitted for clarity
}

ITEM * item = new ITEM;
cout << GetInfo(item, GetLength);  // <- ambiguous error

GetInfo 仅允许双重返回 + ITEM* 参数模式。那么为什么要考虑(而不是丢弃)GetLength 的两个基于字符串的变体?

4

2 回答 2

11

for 的构造函数std::function<...>模板化的,因为它必须能够支持任何类似函数的输入类型。没有可以尝试推断的单一类型,因此您的重载都可以构造;直到后来编译后才出现类型不匹配的错误。

你可以这样做:

GetInfo(item, static_cast<double(*)(ITEM*)>(GetLength));

显式丢弃其他重载。


换句话说,这不起作用的原因是一样的:

void foo(int);
void foo(void*);

struct bar
{
    template <typename T>
    bar(T f)
    {
        f(5);
    }
};

bar b(foo);

尽管 for 的构造函数体bar仅适用于void foo(int),但它希望支持任何f(5)可以工作的函数,因此参数类型是模板化的。这允许任何函数在该位置工作,这意味着编译器无法推断出要使用的单个最佳重载。


我认为一种语言级别的解决方案是让重载集实际上是函子本身。也就是说,给定:

void foo(int);
void foo(void*);

template <typename T>
double foo(int, T);

命名foo(如在bar(foo)或什至只是foo(5))会产生这种类型的实例:

struct __foo_overload_set // internal
{
    // forwarders
    void operator()(int __arg0) const
    {
        // where __foo0 is the zeroth overload, etc...
        return __foo0(__arg0);
    }

    void operator()(void* __arg0) const
    {
        return __foo1(__arg0);
    }

    template <typename __Arg1>
    double operator()(int __arg0, __Arg1&& __arg1) const
    {
        return __foo2(__arg0, std::forward<__Arg1>(__arg1));
    }

    // converters
    typedef void(*__foo0_type)(int);

    operator __foo0_type() const
    {
        return __foo0;
    }

    typedef void(*__foo1_type)(void*);

    operator __foo1_type() const
    {
        return __foo1;
    }

    template <typename T>
    struct __foo2_type
    {
        typedef void(*type)(int, T);
    };

    template <typename T>
    operator typename __foo2_type<T>::type() const
    {
        return __foo2;
    }
};

它本身是可调用的,在我们想要的上下文中编译。(AFAIK,它没有引入任何不存在的歧义,尽管它完全未经测试。)

于 2011-11-16T18:39:25.210 回答
0

你的牙套不匹配。这就是编译器无法理解你的原因

CString GetInfo(ITEM * item, std::function<double ITEM*> fn)
于 2011-11-16T18:36:11.230 回答