Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/163.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;用模板元编程生成函数_C++_Templates_Metaprogramming_C++17 - Fatal编程技术网

C++ C++;用模板元编程生成函数

C++ C++;用模板元编程生成函数,c++,templates,metaprogramming,c++17,C++,Templates,Metaprogramming,C++17,如何使用模板元编程生成函数。我想做的是有一系列基本上做相同事情的函数: Type1 fun1(int arg1,int arg2){ Type1 newType1={}; 新类型1.arg1=arg1; 新类型1.arg2=arg2; 返回newType1; } 类型2 fun2(整数arg1、整数arg2、整数arg3、布尔arg4){ Type2 newType2={}; 新类型2.arg1=arg1; 新类型2.arg2=arg2; 新类型2.arg3=arg3; 新类型2.arg4=ar

如何使用模板元编程生成函数。我想做的是有一系列基本上做相同事情的函数:

Type1 fun1(int arg1,int arg2){
Type1 newType1={};
新类型1.arg1=arg1;
新类型1.arg2=arg2;
返回newType1;
}
类型2 fun2(整数arg1、整数arg2、整数arg3、布尔arg4){
Type2 newType2={};
新类型2.arg1=arg1;
新类型2.arg2=arg2;
新类型2.arg3=arg3;
新类型2.arg4=arg4;
返回newType2;
}
所以基本上我不想自己编写所有这些函数,比如说,我想要一个函数
fun1
,它接受两个int参数,并使用模板将它们分配给类型1的新对象,但是如何

我的想法是有一个模板函数,它接受一个类型(这里是Type1或Type2)并指向这些类型的成员,所以我唯一要做的就是给模板成员指针,它生成接受相应类型参数的函数。

这是一个答案:

在外面做这件事很痛苦。您缺少
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自动生成函数(){
return+[](成员类型参数)->t{
T retval={};
((retval.*PMem)=std::forward(args)),…);
返回返回;
};
}
结构鲍勃{
int x,y;
};
constexpr auto*func=make_func();

除了重载不可用外,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;
  };
}
模板
使用func\u t=t(*)(成员类型);
样板
constexpr func\u t make\u func(){
返回[](成员类型参数)->t{
T retval={};
((retval.*PMem)=std::forward(args)),…);
返回返回;
};
}


有时MSVC在具有多个不同调用约定的无状态lambda上遇到一元运算符
+
问题。上述方法避免了这一问题,但要付出一些代价。

我个人会给
Type1
Type2
适当的构造函数(或确保它们是聚合的)。这将使您可以创建一个变量函数,它只将所有参数转发给构造函数。而且它可能会简化您的代码,以避免首先需要这些函数!您可以使用
一次展开一组值和一组类型…:o我从来没有这样惊讶过2年关于C++ QuicCKS…谢谢,但是现在我怎么能产生一个函数<代码> Foo这实际上是代码> Func<代码>,所以我可以直接调用<代码> FoO(1, 2)< /C> >?(例如,要知道,您的类型有多少字段),目前在任何C++标准中都不支持。@ Kiosto,您介意它是静态对象还是CONExPR函数指针而不是实际函数?@ YAKK ADAMNEVRAUMUNT我不知道,有什么区别?只要我能称之为实际函数,它就很好。
struct A {
  int x, y;
};
struct B {
  A one, two;
};
B func<B, &B::one, &B::two>( {1,2}, {3,4} );
template<class T, auto...PMem, class...Args>
T func( Args&&... args ) {
  T retval = {};
  ( ((retval.*PMem) = std::forward<Args>(args)), ... );
  return retval;
}
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>();    
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;
  };
}