使用返回类型调用模板化指针到成员函数时出错

问题描述 投票:1回答:1
template<typename T, typename F, typename ...Args>
auto f(F h, Args&&... args) -> decltype(h(args...)) {
    T* t = new T(); // Don't worry, my actual code doesn't do this
    return (t->h)(args...);
}

struct G {
    int g() {
        return 5;
    }
};

int main() {
    int k = f<G>(&G::g);
}

微软的编译器说error C2672: 'f': no matching overloaded function founderror C2893: Failed to specialize function template 'unknown-type f(F,Args &&...)'

Clang的编译器说note: candidate template ignored: substitution failure [with T = G, F = int (G::*)(), Args = <>]: called object type 'int (G::*)()' is not a function or function pointererror: no matching function for call to 'f'

我很确定int (G::*)()是一个函数指针......?我错过了什么? (在添加返回类型之前,所有这些都正常工作。)

c++ templates variadic-templates member-function-pointers template-deduction
1个回答
2
投票

我很确定int (G::*)()是一个函数指针......?我错过了什么?

非确切:int (G::*)()是指向非静态方法的指针。这不是完全相同的东西,需要一些不同的语法来调用它。

所以,而不是

return (t->h)(args...);

你应该添加一个*并按如下方式调用h()

return (t->*h)(args...);
// ........^  add this *

decltype()也错了。如果你至少可以使用C ++ 14,你可以避免它,只需使用auto作为返回类型

template <typename T, typename F, typename ...Args>
auto f (F h, Args&&... args) {
    T* t = new T(); 
    return (t->*h)(args...);
}

否则,如果你必须使用C ++ 11,你可以包括<utility>并使用std::declval()如下

template <typename T, typename F, typename ...Args>
auto f(F h, Args&&... args) -> decltype((std::declval<T*>()->*h)(args...)) { 
    T* t = new T(); // .................^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    return (t->*h)(args...);
}

但还有另一种方法来编写你的f()函数:推导返回的类型(所以避免autodecltype()std::declval())和h()的论点

您可以按如下方式编写f()

template<typename R, typename T, typename ... As1, typename ... As2>
R f(R(T::*h)(As1...), As2 && ... args) {
    T* t = new T();
    return (t->*h)(args...);
}

并且你避免明确调用它的G类型

int k = f(&G::g);
// .....^^^^^^^^   no more explicit <G> needed

因为T模板类型是从参数&G::g推导出来的。

© www.soinside.com 2019 - 2024. All rights reserved.