英文:
Getting function object for overload set
问题
This code doesn't work, because &f
creates a function pointer to only one of the two f()
functions, so the compiler doesn't know which one:
#include <iostream>
#include <string>
void f(int i) {
std::cout << "f(int)" << std::endl;
}
void f(std::string str) {
std::cout << "f(std::string)" << std::endl;
}
template<typename Callback>
void call(const Callback& callback) {
callback(1);
callback("a");
}
int main() {
call(&f);
}
它不起作用,因为&f
创建了一个函数指针,只指向两个f()
函数中的一个,所以编译器不知道应该使用哪一个函数。
It works as intended if I instead make a template lambda function like:
call([](const auto& arg) { f(arg); });
如果我改为使用模板lambda函数,它将按预期工作:
Is there a way to do this without writing an extra lambda, that needs to pass all the arguments? For example with a std::bind
expression? Or is there a limitation in the language that the overload for f
only gets resolved in a function call expression?
有没有办法在不编写额外lambda表达式的情况下实现这一点,而且不需要传递所有参数?例如,使用std::bind
表达式?或者是语言中只有在函数调用表达式中才会解析f
的重载的限制?
英文:
This code doesn't work, because &f
creates a function pointer to only one of the the two f()
functions, so the compiler doesn't know which one:
#include <iostream>
#include <string>
void f(int i) {
std::cout << "f(int)" << std::endl;
}
void f(std::string str) {
std::cout << "f(std::string)" << std::endl;
}
template<typename Callback>
void call(const Callback& callback) {
callback(1);
callback("a");
}
int main() {
call(&f);
}
It works as intended if I instead make a template lambda function like
call([](const auto& arg) { f(arg); });
Is there a way to do this without writing an extra lambda, that needs to pass all the arguments? For example with a std::bind
expression? Or is there a limitation in the language that the overload for f
only gets resolved in a function call expression?
答案1
得分: 4
调用的函数也可以通过静态转换进行选择:
int main() {
call(static_cast<void(*)(std::string)>(&f));
}
然而,一旦你决定调用哪个重载,要么是 int
版本,要么是 std::string
版本。
要同时调用 callback(1);
和 callback("a");
,你需要在函数调用时进行重载决议(或者稍后进行,但不能在之前)。最简单的方法是使用 lambda 表达式。
Lambda 表达式在概念上类似于:
struct my_callable {
template <typename T>
void operator()(const T& t) {
f(t); // <---- 重载决议在此发生
}
};
你也可以通过以下方式实现相同的效果:
struct my_callable2 {
void f(int i) {
std::cout << "f(int)" << std::endl;
}
void f(std::string str) {
std::cout << "f(std::string)" << std::endl;
}
};
然而,lambda 表达式很可能会被内联,因此不会真正受益于避免一个函数调用。通过自己编写函数子类也不会减少样板代码。
英文:
The function to be called can also be choosen via a static_cast:
int main() {
call(static_cast<void(*)(std::string)>(&f));
}
However, once you decided which overload to call it is either the int
one or the std::string
one.
To call both callback(1);
and callback("a");
you need the overload resolution at the function call (or later, but not before as above). And the easiest way to do that is to use the lambda.
The lambda is conceptually similar to
struct my_callable {
template <typename T>
void operator()(const T& t) {
f(t); // <---- overload resolution kicks in here
}
};
And you could achieve the same via
struct my_callable2 {
void f(int i) {
std::cout << "f(int)" << std::endl;
}
void f(std::string str) {
std::cout << "f(std::string)" << std::endl;
}
};
However, the lambda is likely to be inlined, hence no real benefit of avoiding one function call is to be expected. And it wont get any less boilerplate by writing the functor yourself.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论