如何使用模板元编程生成函数。 我想做的是有一堆函数,它们基本上做同样的事情:
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)和指向这些类型的成员的指针,所以我要做的唯一一件事就是给模板指向成员的指针,然后它生成一个接受相应类型参数的函数。
这是一个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;
}
测试代码:
struct Bob {
int x,y;
};
int main() {
Bob b = func<Bob, &Bob::x, &Bob::y>( 2, 3 );
(void)b;
}
活生生的例子。
你也可以在没有匹配类型的情况下完美前进。 这有一个缺点,那就是这不起作用:
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;
}
在C++17之外做这件事是一件痛苦的事。 缺少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>();
活生生的例子。
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;
};
}
活生生的例子。
有时,MSVC在具有多个不同调用约定视素的无状态lambda上遇到一元运算符+
的问题。 上面的方法避免了这个问题,但代价是一些样板。
本文向大家介绍浅谈C++模板元编程,包括了浅谈C++模板元编程的使用技巧和注意事项,需要的朋友参考一下 所谓元编程就是编写直接生成或操纵程序的程序,C++ 模板给 C++ 语言提供了元编程的能力,模板使 C++ 编程变得异常灵活,能实现很多高级动态语言才有的特性(语法上可能比较丑陋,一些历史原因见下文)。模板元编程的根在模板。模板的使命很简单:为自动代码生成提供方便。提高程序员生产率的一个非常有效
技术的学习是一个登山的过程。第一章是最为平坦的山脚道路。而从这一章开始,则是正式的爬坡。无论是我写作还是你阅读,都需要付出比第一章更多的代价。那么问题就是,付出更多的精力学习模板是否值得? 这个问题很功利,但是一针见血。因为技术的根本目的在于解决需求。那C++的模板能做什么? 一个高(树)大(新)上(风)的回答是,C++里面的模板,犹如C中的宏、C#和Java中的自省(restropection)
表单创建页面工作正常,但我需要表单编辑页面。我想我需要一个att,但我找不到。我怎么做? 管理面板的呈现表单 在此输入图像描述 示例我的数据库行(json) {“type”:“header”,“subtype”:“h1”,“label”:“\u003Ch2\u003E\u0130\u015f Ba\u015fvuru Formu\u003C/h2\u003E”,“access”:false},{“
问题内容: 静态元编程(也称为“模板元编程”)是一种出色的C ++技术,它允许在编译时执行程序。阅读以下规范元编程示例后,一个灯泡突然在我的脑海中闪过: 如果要了解有关C ++静态元编程的更多信息,最好的资源是什么(书籍,网站,在线课件,等等)? 问题答案: [回答我自己的问题] 到目前为止,我发现的最好的介绍是Krzysztof Czarnecki和Ulrich W. Eisenecker撰写的
Boost.Call_traits 这个库提供了传递参数给函数的最好方法的自动演绎,依据参数的类型。例如,当传递的是如int 和 double这样的内建类型,最高效的方式是传值。对于用户自定义类型,则传送const引用通常更好。Call_traits为你自动选择正确的参数类型。这个库还有助于声明参数为引用,而不用冒引用到引用的风险(在C++这是非法的)。Call_traits常用于要求以最高效方式
本文向大家介绍C++模板元编程实现选择排序,包括了C++模板元编程实现选择排序的使用技巧和注意事项,需要的朋友参考一下 前言 模板在C++一直是比较神秘的存在。 STL 和 Boost 中都有大量运用模板,但是对于普通的程序员来说,模板仅限于使用。在一般的编程中,很少会有需要自己定义模板的情况。但是作为一个有理想的程序员,模板是一个绕不过去的坎。由于C++标准的不断改进,模板的能力越来越强,使用范
我有一个问题,我想在下面的代码中专门化模板类的模板成员函数。这个问题的答案是模板类成员函数的显式特化,这似乎表明它无法完成。这是正确的吗,如果是这样,我可以使用任何解决方法,以便在编译时通过内联inc函数进行扩展? 非常感谢! g吐槽道: test2.cpp:32:13: 错误: 非命名空间作用域中的显式专用化 'struct IdxIterator' test2.cpp:32:25: 错误: 非
在《 C++函数重载》一节中,为了交换不同类型的变量的值,我们通过函数重载定义了四个名字相同、参数列表不同的函数,如下所示: 这些函数虽然在调用时方便了一些,但从本质上说还是定义了三个功能相同、函数体相同的函数,只是数据的类型不同而已,这看起来有点浪费代码,能不能把它们压缩成一个函数呢? 能!可以借助本节讲的函数模板。 我们知道,数据的值可以通过函数参数传递,在函数定义时数据的值是未知的,只有等到