为什么C将此视为模糊函数引用

为什么我的编译器会将以下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的两个基于字符串的变体呢?

解决方法

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);

即使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,它没有引入任何尚未存在的含糊之处,尽管它完全没有经过测试.)

相关文章

对象的传值与返回说起函数,就不免要谈谈函数的参数和返回值...
从实现装饰者模式中思考C++指针和引用的选择最近在看...
关于vtordisp知多少?我相信不少人看到这篇文章,多半是来自...
那些陌生的C++关键字学过程序语言的人相信对关键字并...
命令行下的树形打印最近在处理代码分析问题时,需要将代码的...
虚函数与虚继承寻踪封装、继承、多态是面向对象语言的三大特...