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

发布于 2024-11-10 14:32:17 字数 836 浏览 3 评论 0原文

可能的重复:
为什么我的 C++ 编译器无法推导出模板参数用于升压功能?
不是模板参数(其类型的 std::function 的签名)?

我有以下内容:

#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 解决方案?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

单调的奢华 2024-11-17 14:32:18

在 C++0x 中,可以使用 SFINAE 使其正常工作。然而,据我所知,MSVC 的 SFINAE bug 使它们无法实现,而 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); }
}

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); }
}
尽揽少女心 2024-11-17 14:32:17

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

所以不,您需要以某种方式提供与其中一个函数的精确匹配。您可以引入 Foo 的其他重载实例,例如

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

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文