C++中的过载分辨率可能是一个过于复杂的过程.理解控制重载决策的所有C++规则需要花费大量精力.最近我发现在参数列表中存在重载函数的名称会增加重载决策的复杂性.由于它恰好是一个广泛使用的案例,我发布了一个问题,并得到了一个答案,使我能够更好地理解该过程的机制.然而,在iostreams的背景下提出这个问题似乎有点分散了答案的焦点,从正在解决的问题的本质.所以我开始深入研究并提出了其他要求对问题进行更详细分析的例子.这个问题是一个介绍性问题,然后是一个更复杂的问题.
假设一个人完全理解重载解析如何在没有自身名称的重载函数的情况下工作.必须对他们对重载决策的理解做出哪些修改,以便它还包括使用重载函数作为参数的情况?
鉴于这些声明:
void foo(int) {}
void foo(double) {}
void foo(std::string) {}
template<class T> void foo(T* ) {}
struct A {
A(void (*)(int)) {}
};
void bar(int x, void (*f)(int)) {}
void bar(double x, void (*f)(double)) {}
void bar(std::string x, void (*f)(std::string)) {}
template<class T> void bar(T* x, void (*f)(T*)) {}
void bar(A x, void (*f2)(double)) {}
Run Code Online (Sandbox Code Playgroud)
下面的表达式导致名称的以下解析foo(至少使用gcc 5.4):
bar(1, foo); // foo(int)
// but if foo(int) is removed, foo(double) takes …Run Code Online (Sandbox Code Playgroud) 我试图编写一个函数来转发可变参数模板函数的参数,类似于std::invoke.这是代码:
#include <functional>
template<class... Args>
void f(Args&&... args) { }
template<template<class...> class F, class... Args>
void invoke(F<Args...> f, Args&&... args) {
f(std::forward<decltype(args)>(args)...);
}
int main() {
invoke(f, 1, 2, 3);
std::invoke(f, 1, 2, 3);
}
Run Code Online (Sandbox Code Playgroud)
但是,我invoke和std::invoke编译都失败了.g ++抱怨它无法推断出模板参数template<class ...> class F.那么是否可以在没有显式模板特化的情况下调用可变参数模板函数?