[英]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 c++17 answer:这是c++17答案:
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;
}
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 c++17 is a pain.在c++17之外执行此操作很痛苦。 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>();
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;
};
}
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.