C++ 考虑引用和常数的变量函数包装器

C++ 考虑引用和常数的变量函数包装器,c++,templates,variadic-templates,C++,Templates,Variadic Templates,我创建了一个小的函数包装器示例。我想让包装器考虑调用的函数是否是使用(const)引用,这意味着输出将是4/5而不是4/4,但是如果包装的函数不使用它们,我不想强制引用使用。 #include <iostream> #include <string> struct a { static void run(int cref) { cref = 5; }; }; struct b { static void run(int &cref) {

我创建了一个小的函数包装器示例。我想让包装器考虑调用的函数是否是使用(const)引用,这意味着输出将是4/5而不是4/4,但是如果包装的函数不使用它们,我不想强制引用使用。
#include <iostream>
#include <string>

struct a {
  static void run(int cref) {
    cref = 5;
  };
};

struct b {
  static void run(int &cref) {
    cref = 5;
  };
};

template <class FTor>
struct foo {
    template <class ... Args>
    static void wrapper(Args ... args) {
      FTor::run(args ...);
    }
};


int main()
{
    int bar = 4;
    foo<a>::wrapper(bar);
    std::cout << bar;

    foo<b>::wrapper(bar);
    std::cout << bar;
}
#包括
#包括
结构a{
静态无效运行(int cref){
cref=5;
};
};
结构b{
静态无效运行(int和cref){
cref=5;
};
};
模板
结构foo{
模板
静态无效包装器(Args…Args){
FTor::运行(参数…);
}
};
int main()
{
int bar=4;
foo::包装(条);

std::cout这是为了回答我对OP请求可能存在的误解,因为简单完美转发解决了描述的场景,而无需借助包装函数参数的类型推断

原始答案:至少对于您正在演示的受限用例,您可以使用一个小型类型trait struct从函子的参数类型推断传递给
wrapper()
的单个参数的类型:

#include <iostream>
#include <string>

struct a {
  static void run(int cref) {
    cref = 5;
  };
};

struct b {
  static void run(int &cref) {
    cref = 5;
  };
};

template <typename>
struct ArgType;

template <typename R, typename A>
struct ArgType<R(A)>
{ using type = A; };

template <class FTor>
struct foo {
    static void wrapper(typename ArgType<decltype(FTor::run)>::type args) {
      FTor::run(args);
    }
};

int main()
{
    int bar = 4;
    foo<a>::wrapper(bar);
    std::cout << bar;

    foo<b>::wrapper(bar);
    std::cout << bar;
}

注意,这将不支持从包装器内部进行完美转发,如
wrapper()
这里本身并不是*类型推断上下文的一部分`--与您的代码段相反,它推断但不基于您希望它推断的内容。我希望有时间为可变函数模板添加一个通用解决方案,例如在您的代码段中,包括完美转发。

使用完美转发怎么样

template <class FTor>
struct foo {
    template <class ... Args>
    static void wrapper(Args && ... args) {
      FTor::run(std::forward<Args>(args) ...);
    }
};
模板
结构foo{
模板
静态无效包装(Args&…Args){
FTor::run(std::forward(args)…);
}
};

这样,参数对输入的任何引用限定都会传递给内部函数。

添加一个接受常量引用的重载?但这是一个单独的参数,不能将其转换为一个包。@bipll Roget,抱歉。编辑以更正。只是出于兴趣,与删除的&&solution@dgrat所以rry在被删除之前我一定错过了它。这个有点不完整的答案的实质是基于特定
run()的签名定义
wrapper()
方法
本身,因此它将采用相同的类型,因此您的引用始终是一个引用。如果函数重载或函数模板,这也将不起作用。我不确定是否遵循,如何
wrapper()
推断它的参数类型不是基于你给它提供了什么,而是基于包装的函数签名,我认为这是我想要的运算。@怀疑论者根据我对这个问题的解释,我认为他只是想让他提供的例子起作用。我想他实际上并不在乎
包装器
是否能推断出类型。编辑我的回答反映了这一事实,示例。@MarekR是的,您也可以传入
std::ref
来绕过复制函数参数,尽管如果您忘记了这样做,您不会得到编译错误。但是,通过完美转发,如果传入错误的cv ref限定,您会得到编译错误。
template <class FTor>
struct foo {
    template <class ... Args>
    static void wrapper(Args && ... args) {
      FTor::run(std::forward<Args>(args) ...);
    }
};