基于用户表达式在编译时参数化函数



我正在编写一个 C++11 库,用户需要在其中指定要使用的struct和要使用的元素(按顺序(。例如:

// Declaration
struct MyData{ double x, y ,z;};
...
// Use
MyClass<MyData, y, x> myobj;
MyData mydata;
myobj.set(mydata);
...

然后,MyClass应生成不同的函数来循环访问参数包,但将参数视为表达式。为此,我声明了一个带有参数包的类:

template<class T, class ... G>
class MyClass{
    std::vector<double*> var;
    public:
    Test();
    void set(T const& var_);
 };

然后我不知道如何生成set()函数。行为应类似于以下伪代码:

 template<class T, class ... G>
 void Test<T, G...>::set(T const& var_){
 unsigned pos = 0;
 for(unsigned i =0; i < sizeof...(G); i++)
     *var[i] = var_.G(i);
}

在这种情况下,MyClass<MyData,y,x>将产生:

...
*var[0] = var_.y;
*var[1] = var_.x;
...
在我看来

,您正在寻找一种将指向结构/类成员的可变参数序列作为模板参数传递的方法以及使用它们的方法。

指针的可变参数序列作为模板参数传递给结构/类成员的语法如下

template <typename T, typename U, U T::* ... Ms>
struct MyClass
 { /* something */ };

但是,在您的情况下,您已将U类型固定为 double,因此您可以简化如下

template <typename T, double T::* ... Ms>
struct MyClass
 { /* something */ };

要在set()中获取正确的值,您可以制作如下内容

void set (T const & v0)
 {
   using unused = int[];
   (void)unused { 0, (var.emplace_back(v0.*Ms), 0) ... };
 }

请注意,为了简化起见,我已将您的var向量更改为 double s,而不是指向 đouble s 的指针。

下面是一个完整的(简化(示例

#include <vector>
#include <iostream>
struct MyData
 { double x, y ,z; };
template <typename T, double T::* ... Ms>
struct MyStruct
 { 
   std::vector<double> var;
   void set (T const & v0)
    {
      using unused = int[];
      (void)unused { 0, (var.emplace_back(v0.*Ms), 0) ... };
    }
 };
int main ()
 {
   MyData md { 1.0, 2.0, 3.0 };
   MyStruct<MyData, &MyData::y, &MyData::x>  ms;
   ms.set(md);
   for ( auto const & d : ms.var )
      std::cout << d << ' ';
   std::cout << std::endl;
 }

另一种方法是让用户指定元组和索引:

struct MyData : std::tuple<double, double, double> {
    enum Names { X, Y, Z }; // Named indexes.
};
template<class T, size_t... Indexes>
class MyClass {
    std::vector<double*> var;
public:
    void set(T const& t) {
        auto unused = { (*var[Indexes] = std::get<Indexes>(t), 1)... };
        static_cast<void>(unused);
    }
};
int main() {
    MyClass<MyData, MyData::X, MyData::Y> myobj;
    MyData mydata;
    myobj.set(mydata);
}

最新更新