我有这个简化的代码,它包含一个带有静态函数的类,它存储在map:
中#include <iostream>
#include <functional>
#include <map>
class A {
public:
static void f(const std::string &s) { std::cout << s; }
};
std::map<std::string, std::function<void(std::string const &)>> fs;
int main() {
fs["f"] = &A::f;
fs["f"]("hello");
}
这将打印预期的 hello 。
如果我使用:
重载f(),则会出现问题 static void f(const std::string &s, int c) { while(c-->0) { std::cout << s; } }
这会导致错误:
error: no viable overloaded '='
fs["f"] = &A::f;
~~~~~~~ ^ ~~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/functional:2241:7: note: candidate function not viable: no overload of 'f' matching 'const std::function<void (const std::basic_string<char> &)>' for 1st argument
operator=(const function& __x)
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/functional:2259:7: note: candidate function not viable: no overload of 'f' matching 'std::function<void (const std::basic_string<char> &)>' for 1st argument
operator=(function&& __x)
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/functional:2273:7: note: candidate function not viable: no overload of 'f' matching 'nullptr_t' for 1st argument
operator=(nullptr_t)
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/functional:2302:2: note: candidate template ignored: couldn't infer template argument '_Functor'
operator=(_Functor&& __f)
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/functional:2311:2: note: candidate template ignored: couldn't infer template argument '_Functor'
operator=(reference_wrapper<_Functor> __f) noexcept
^
然而,调用这两个函数是有效的:
A::f("hello ");
A::f("echo ", 3);
所以,我的问题是:
答案 0 :(得分:2)
为什么即使运算符=似乎存在,此代码也无法编译 和函数,如果我不重载f()?
因为编译器不知道要选择哪个重载。怎么可能?没有标准可以决定哪一个更适合。每个std::function
允许分配任意函数对象,并且不检查任何签名。如果您只想保存此特定签名的函数指针,则应该适当地声明map
。
如何在不同时兼顾两种功能的情况下使其工作 名字?
如前所述,它通过将表达式转换为特定类型的函数指针来工作。
fs["f"] = static_cast<void(*)(std::string const&)>( &A::f );
这样就不会出现歧义;只有一个重载可以转换为此函数到指针类型。
如果这更常出现,那么typedef是可行的。
或者是一个小帮助类模板:
template <typename... Exact>
struct funptr
{
template <typename R>
constexpr auto operator()(R(*p)(Exact...)) -> decltype(p)
{ return p; }
};
fs["f"] = funptr<std::string const&>()(&A::f);