简体   繁体   English

C++ 使用模板元编程生成 function

[英]C++ generate function with template metaprogramming

How can I generate a function using template metaprogramming.如何使用模板元编程生成 function。 What I want to do is have a bunch of functions that basically do the same thing:我想要做的是有一堆基本上做同样事情的函数:

Type1 fun1(int arg1, int arg2) {
  Type1 newType1 = {};
  newType1.arg1 = arg1;
  newType1.arg2 = arg2;

  return newType1;
}

Type2 fun2(int arg1, int arg2, int arg3, bool arg4) {
  Type2 newType2 = {};
  newType2.arg1 = arg1;
  newType2.arg2 = arg2;
  newType2.arg3 = arg3;
  newType2.arg4 = arg4;

  return newType2;
}

So basically I don't want to write all these functions myself, I want for example say that I want a function fun1 that takes two int arguments and assign them to a new object of Type1 using templates but how?所以基本上我不想自己编写所有这些函数,例如我想说我想要一个 function fun1 ,它需要两个 int arguments 并使用模板将它们分配给一个新的 object 但是如何?

My idea is to have a template function that takes a type (here Type1 or Type2) and pointers-to-members of these types, so the only thing I have to do is give the template the pointers-to-members and it generates the function that takes arguments of the corresponding type.我的想法是有一个模板 function 接受一个类型(这里是 Type1 或 Type2)和指向这些类型的成员的指针,所以我唯一要做的就是给模板指向成员的指针,它会生成function 取对应类型的 arguments。

This is a answer:这是答案:

template<auto PMem>
struct member_type {};
template<class T, class M, M(T::*ptr)>
struct member_type<ptr> { using type=M; };
template<auto PMem>
using member_type_t=typename member_type<PMem>::type;

template<class T, auto...PMem>
T func( member_type_t<PMem>... args ) {
  T retval = {};
  ( ((retval.*PMem) = std::forward<member_type_t<PMem>>(args)), ... );
  return retval;
}

test code:测试代码:

struct Bob {
  int x,y;
};

int main() {
    Bob b = func<Bob, &Bob::x, &Bob::y>( 2, 3 );
    (void)b;
}

live example .活生生的例子

You can also perfect forward without matching types.您也可以在不匹配类型的情况下完善前进。 This has the downside that this doesn't work:这样做的缺点是不起作用:

struct A {
  int x, y;
};
struct B {
  A one, two;
};
B func<B, &B::one, &B::two>( {1,2}, {3,4} );

but it does eliminate some boilerplate above, and it could remove a redundant move per member field.但它确实消除了上面的一些样板,它可以消除每个成员字段的冗余移动。

To do that, simply drop the member_type helper completely:为此,只需完全删除member_type助手:

template<class T, auto...PMem, class...Args>
T func( Args&&... args ) {
  T retval = {};
  ( ((retval.*PMem) = std::forward<Args>(args)), ... );
  return retval;
}

Doing this outside of is a pain.之外执行此操作很痛苦。 You lack auto parameters and ... expansion of statements.您缺少auto参数和...扩展语句。 The second is relatively easy to work around with some boilerplate, but the first makes your desired syntax basically impossible;第二个使用一些样板文件相对容易解决,但第一个使您想要的语法基本上不可能; you may be reduced to using macros.您可能会减少使用宏。

If you don't want <> syntax:如果你不想要<>语法:

template<class T, auto...PMem>
constexpr auto make_func() {
  return +[]( member_type_t<PMem>... args )->T {
    T retval = {};
    ( ((retval.*PMem) = std::forward<member_type_t<PMem>>(args)), ... );
    return retval;
  };
}

struct Bob {
  int x,y;
};

constexpr auto* func = make_func<Bob, &Bob::x, &Bob::y>();    

Live example .活生生的例子

A constexpr function pointer should be treated nearly indistinguishably from a function, except overloading isn't available. constexpr function 指针应该与 function 几乎没有区别,除非重载不可用。

In MSVC you might have to disambiguate the function pointer type like this:在 MSVC 中,您可能必须像这样消除 function 指针类型的歧义:

template<class T, auto...PMem>
using func_t = T(*)(member_type_t<PMem>...);

template<class T, auto...PMem>
constexpr func_t<T, PMem...> make_func() {
  return []( member_type_t<PMem>... args )->T {
    T retval = {};
    ( ((retval.*PMem) = std::forward<member_type_t<PMem>>(args)), ... );
    return retval;
  };
}

Live example .活生生的例子

Sometimes MSVC has problems with unary operator + on stateless lambdas having multiple different calling convention optoins.有时MSVC 在具有多个不同调用约定选项的无状态 lambda 上的一元运算符+存在问题。 The above avoids that issue, at the cost of a bit of boilerplate.以上避免了这个问题,但代价是一些样板。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM