使用std :: function进行隐式转换

时间:2011-05-31 21:23:54

标签: c++ c++11 implicit-conversion overloading

  

可能重复:
  Why can't my C++ compiler deduce template argument for boost function?
  Isn't the template argument (the signature) of std::function part of its type?

我有以下内容:

#include <functional>

void Foo( std::function<void()>    );
void Foo( std::function<void(int)> );
void Bar();

int main()
{
  Foo( Bar );     // Error: ambiguous
  Foo( [](){} );  // Error: ambiguous

  Foo( std::function<void()>( Bar    ) ); // Ok
  Foo( std::function<void()>( [](){} ) ); // Ok
}

我可以在main()中使用前两行而不使用最后两行中的函数样式转换吗?也许使用std :: enable_if解决方案?

2 个答案:

答案 0 :(得分:4)

对Foo的任何调用,其参数不完全是std::function<void()>std::function<void(int)>之一,将导致无法解决的重载问题。即使是愚蠢的事情,如Foo(1)Foo("abc")。这是因为std::function的构造函数是模板化的并且接受任何类型。 std::function<void()>(1)在实例化时会失败,但在实例化之前会发生重载解析。

所以不,你需要以某种方式提供与其中一个功能的完全匹配。您可以引入其他重载的Foo实例,例如

void Foo(void (*)());
void Foo(void (*)(int));

这将导致更好的匹配,并且不再有歧义。

答案 1 :(得分:3)

可以在C ++ 0x中使用SFINAE使其正常工作。但是,据我所知,MSVC的SFINAE漏洞使它们无法实现,并且GCC的图书馆实施者似乎没有注意到,所以遗憾的是这不起作用。

我猜你也可以试试某种make_function。请原谅我的可变参数模板,已经有一段时间了。

template<typename T> struct function_proxy {
    T f;
    template<typename Ret, typename... T> operator std::enable_if<std::is_same<Ret, decltype(f(std::declval<T>()...))>::value, std::function<Ret(T...)>>::type () {
        return std::function<Ret(T...)>(f);
    }
};
template<typename T> function_proxy<T> make_function(T&& t) {
    return function_proxy { std::forward<T>(t); }
}