c++ - 模板函数中 const 引用的类型推导

标签 c++ templates template-function universal-reference

下面我有一个名为 ProxyCall 的模板函数,它接受一个对象、一个成员函数及其参数。它只是将调用转发给成员函数。

我希望能够在不使用模板限定符的情况下调用该函数(想象一下大量带有多个参数的此类调用)。类型推导大部分都有效,但当我尝试像示例中那样传递 const 引用参数时,编译器(msvc 和 gcc 4.9)会感到厌烦。

#include <string>

struct Widget {
    void f(const std::string& s, bool b) {}
};


template<typename T, typename... Args>
void ProxyCall(T &obj, void(T::*method)(Args...), Args&&... args) {
    (obj.*method)(std::forward<Args>(args)...);
}


int main(int argc, char* argv[])
{
    Widget w;
    std::string s;

    ProxyCall<Widget, const std::string&, bool>(w, &Widget::f, s, true); // OK
    ProxyCall(w, &Widget::f, (const std::string&)s, true); // also OK

    ProxyCall(w, &Widget::f, s, true); // ERROR: template parameter is ambiguous
    return 0;
}

我的问题是:如何修改上面的代码,以便编译器自动推导类型,而无需求助于显式模板限定符或显式转换。考虑到编译器已经从 Widget::f 的签名中知道确切的参数类型,这似乎应该是可能的。

最佳答案

template<typename T, typename... Args>
void ProxyCall(T &obj, void(T::*method)(Args...), Args&&... args) {
    (obj.*method)(std::forward<Args>(args)...);
}

Args 是从 ProxyCall 的第二个参数和尾随参数推导出来的。
在你的第三种情况下,由于 s 不是 constArgs 被推断为 [std::string&, bool](记忆引用折叠和转发引用的规则)。但是,成员函数签名明显不同。于是Args中的第一个类型推导了两个不同的类型,导致推导失败。

相反,为了引用限定符,使参数类型和参数独立 - 并转发对象参数:

template<typename T, typename F, typename... Args>
void ProxyCall(T&& obj, F method, Args&&... args) {
    (std::forward<T>(obj).*method)(std::forward<Args>(args)...);
}

关于c++ - 模板函数中 const 引用的类型推导,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28608753/

相关文章:

c++ - 将一个函数的 vector + map 版本合并为一个兼容的版本

c++ - 根据对值对多维映射进行排序

c++ - 在虚拟继承的情况下如何对待祖 parent 类的成员?

javascript - 仅当给定 Handlebar 变量时才显示周围的 HTML

c++ - 命名空间模板函数和隐藏的命名空间变量

c++ - C++1z 标准如何在模板函数声明中定义属性的正确位置?

c++ - 依赖模板函数的 Pimpl 习语实现

c++ - 长时间运行的 std::async 会饿死其他 std::async 吗?

c++ - 如何使用c++的ofstream方法删除文件?

c++ - 如何匹配模板类中的模板友元函数