开发者

Implicit conversions with std::function [duplicate]

This question already has answers here: Closed 11 years ago.

Possible Duplicates:

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?

I have the following:

#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
}

Can I make the first two lines in main() work without the function-style cast in the last two lines? Perhaps with a std::enable_if solution?


Any call to Foo with a parameter which is not exactly one of std::function<void()> and std::function<void(int)> will result in an unresolved overloading. Even silly things like Foo(1) or Foo("abc"). This is because constructors of std::function are templated and accept any type. std::function<void()>(1) would fail at instantiation, but overload resolution happens before instantiation.

So no, you need to provide an exact match to one of the functions, one way or another. You may introduce other overloaded instances of Foo, like

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

and this will result in a better match and the ambiguity will be no more.


It is possible to use SFINAE to make this work correctly, in C++0x. However, MSVC's SFINAE bugs make it impossible for them, as far as I know, and GCC's library implementers don't seem to have noticed, so this unfortunately doesn't work.

You could also try some sort of make_function, I guess. Excuse my variadic templates, it's been a while.

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜