如何以可变参数作为模板参数编写成员函数

问题描述 投票:0回答:2

是否可以像下面这样在C ++ 14中编写模板函数

这里是样本https://godbolt.org/z/9gRk-t

// pseudo code

#include <type_traits>

template <typename T, typename R, typename... Args>
decltype(auto) Call(T& obj, R(T::*mf)(Args...), Args&&... args) 
{
  return (obj.*mf)(std::forward<Args>(args)...);
}

所以,对于一个测试班

struct Test 
{
  int Func(){return 1;};
  bool Func(bool){return true;};  // overload

  void FuncInt(int){};
};

下面的用例的模板模型工作(但失败)

int main()
{
  Test test;

  // for overload case
  auto a = Call<int()>(test, &Test::Func);
  auto b = Call<bool(bool)>(test, &Test::Func, true);

  // for non-overload case
  Call(test, &Test::FuncInt, 1);

  return 0;
}

提供错误信息。

#1 with x64 msvc v19.24
example.cpp
<source>(23): error C2672: 'Call': no matching overloaded function found
<source>(23): error C2770: invalid explicit template argument(s) for 'decltype(auto) Call(T &,R (__cdecl T::* )(Args...),Args &&...)'
<source>(5): note: see declaration of 'Call'
<source>(24): error C2672: 'Call': no matching overloaded function found
<source>(24): error C2770: invalid explicit template argument(s) for 'decltype(auto) Call(T &,R (__cdecl T::* )(Args...),Args &&...)'
<source>(5): note: see declaration of 'Call'
Compiler returned: 2
c++ c++11 templates c++14 variadic-templates
2个回答
0
投票

我已经知道了。它像std :: men_fn一样安静。

这是下面的代码和示例https://godbolt.org/z/NoWPV_


#include <type_traits>

template<typename T>
struct Proxy
{
    template<typename R, typename ...Args>
    decltype(auto) Call(T& obj, R T::*mf, Args&&... args)
    {
        return (obj.*mf)(std::forward<Args>(args)...);
    }
};

struct Test 
{
  int Func(){return 1;};
  bool Func(bool){return true;};  // overload

  void FuncInt(int){};
};

int main()
{
  Test test;
  Proxy<Test> proxy;

  // for overload case
  auto a = proxy.Call<int()>(test, &Test::Func);
  auto b = proxy.Call<bool(bool)>(test, &Test::Func, true);

  // for non-overload case
  proxy.Call(test, &Test::FuncInt, 1);

  return 0;
}

0
投票

问题与

template <typename T, typename R, typename... Args>
decltype(auto) Call(T& obj, R(T::*mf)(Args...), Args&&... args)

Args被推导两次,并且应该相同。

有几种解决此问题的方法:

  • 添加额外的模板参数:

    template <typename T, typename R, typename... Args, typename ... Ts>
    decltype(auto) Call(T& obj, R(T::*mf)(Args...), Ts&&... args)
    {
        return (obj.*mf)(std::forward<Ts>(args)...);
    }
    
  • 或使参数不可推论(我使用C ++ 20中的std::type_identity:]

    std::type_identity
  • 或更改完全签名:

    template <typename T, typename R, typename... Args>
    decltype(auto) Call(T& obj, R(T::*mf)(Args...), std::type_identity_t<Args>... args)
    {
        return (obj.*mf)(std::forward<Args>(args)...);
    }
    
© www.soinside.com 2019 - 2024. All rights reserved.