gpt4 book ai didi

c++ - C++使用模板元编程生成函数

转载 作者:行者123 更新时间:2023-12-01 14:39:16 24 4
gpt4 key购买 nike

如何使用模板元编程生成函数。我想做的是有一堆基本上可以完成相同操作的函数:

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;
}

因此,基本上我不想自己编写所有这些函数,例如,我想说一个函数 fun1,它接受两个int参数,并使用模板将它们分配给Type1的新对象,但是如何?

我的想法是要有一个接受一个类型(这里是Type1或Type2)和这些类型的成员指针的模板函数,因此,我唯一要做的就是为模板提供该成员的指针,并生成接受相应类型参数的函数。

最佳答案

这是的答案:

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;
}

测试代码:
struct Bob {
int x,y;
};

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

live example

您也可以在不匹配类型的情况下完善前进。不利之处是,这行不通:
struct A {
int x, y;
};
struct B {
A one, two;
};
B func<B, &B::one, &B::two>( {1,2}, {3,4} );

但是它确实消除了上面的一些样板,并且可以消除每个成员字段的多余举动。

为此,只需完全删除 member_type帮助器:
template<class T, auto...PMem, class...Args>
T func( Args&&... args ) {
T retval = {};
( ((retval.*PMem) = std::forward<Args>(args)), ... );
return retval;
}

之外执行此操作很痛苦。您缺少 auto参数和 ...语句扩展。第二种方法相对容易处理一些样板,但是第一种方法使所需的语法基本上变得不可能。您可能会减少使用宏。

如果您不想使用 <>语法:
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

constexpr函数指针应该与函数几乎没有区别,除非没有重载。

在MSVC中,您可能必须消除函数指针类型的歧义,如下所示:
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

有时 MSVC会在具有多个不同的调用约定视标的无状态lambda上使用一元运算符 +产生问题。上面的方法避免了这个问题,但要花一些时间。

关于c++ - C++使用模板元编程生成函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62324504/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com