当前位置: 首页 > 知识库问答 >
问题:

可变参数子集

严成礼
2023-03-14

我试图获取当前类包装器的可变参数子集,以实例化一个新的变量

目前我有:

// Reference: https://stackoverflow.com/questions/27941661/generating-one-class-member-per-variadic-template-argument
// Template specialization
template<typename T, typename... Next> class VariadicClass;

// Base case extension
template <typename T>
class VariadicClass<T> {
private:
    T value_;
protected:
    void SetField(T & value) {
        value_ = value;
    }

    T & GetField() {
        return value_;
    }
};

// Inductive case
template <typename T, typename ... Next>
class VariadicClass : public VariadicClass<T>, public VariadicClass<Next...> {
public:

    // Copy the values into the variadic class
    template <typename F>
    void Set(F f) {
        this->VariadicClass<F>::SetField(f);
    }

    // Retrieve by reference
    template <typename F>
    F & Get() {
        return this->VariadicClass<F>::GetField();
    }
};

我想实现以下目标:

[C]: A subset of Args...

VariadicClass<[C]> * Filter(VariadicClass<Args...> input) {
   return new VariadicClass<[C]>(GetSubsetFrom(input, [C]));
}

VariadicClass<int, bool, char> class1;
VariadicClass<int, bool> * variadic = Filter(class1);

您可以假设每个类型在变量类中只存在一次,并且我将始终请求当前变量类型的子集。我不知道这在C11中是否可行?谢谢你的帮助。

共有2个答案

长孙作人
2023-03-14

首先,我认为您不应该编写自己的变量类,因为我们已经有了std::tuple

我想知道你坐在c 11上,因为它很旧了。即使c 14也过时了,但是如果你可以切换,解决方案非常简单:

template < typename DATA, typename FILTER, std::size_t... Is>
auto Subset_Impl( const DATA& data, FILTER& filter, std::index_sequence<Is...> )
{
    filter = { std::get< typename std::remove_reference<decltype( std::get< Is >( filter ))>::type>( data )... };
}

template < typename DATA, typename FILTER, typename IDC = std::make_index_sequence<std::tuple_size<FILTER>::value >>
auto Subset( const DATA& data, FILTER& filter )
{
    return Subset_Impl( data, filter,  IDC{} );
}

int main()
{
    std::tuple< int, float, std::string, char > data { 1, 2.2, "Hallo", 'c' };
    std::tuple< float, char > filter;

    Subset( data, filter );

    std::cout << std::get<0>( filter ) << " " << std::get<1>( filter ) << std::endl;
}

如果你真的想坐在过时的标准上,你可以很容易地实现标准库中缺失的部分。这里回答了一个相关的问题:获取d::元组的一部分

如何定义帮助模板也可以看到:https://en.cppreference.com/w/cpp/utility/integer_sequence

林亦
2023-03-14

在我看来,您正试图重新发明轮子(在本例中,“轮子”是std::tuple)。

不管怎样,你问的对我来说很简单

template <typename ... As1, typename ... As2>
VariadicClass<As1...> * Filter(VariadicClass<As2...> in)
 {
   using unused = int[];

   auto ret = new VariadicClass<As1...>();

   (void)unused { 0, (ret->template Set<As1>(in.template Get<As1>()), 0)... };

   return ret;
 }

我看到的问题是As1...类型(返回的VariadicClass类型)不能由返回的值推断,所以您不能写入

 VariadicClass<int, bool> * variadic = Filter(class1);

您必须将显式为1 类型调用过滤器(),所以

 VariadicClass<int, bool> * variadic = Filter<int, bool>(class1);

或者,也许更好,

 auto variadic = Filter<int, bool>(class1);

下面是一个完整的编译示例

#include <iostream>

template <typename, typename...>
class VariadicClass;

template <typename T>
class VariadicClass<T>
 {
   private:
      T value_;

   protected:
      void SetField (T & value)
       { value_ = value; }

      T & GetField ()
       { return value_; }
 };

template <typename T, typename ... Next>
class VariadicClass : public VariadicClass<T>, public VariadicClass<Next...>
 {
   public:
      template <typename F>
      void Set (F f)
       { this->VariadicClass<F>::SetField(f); }

      template <typename F>
      F & Get()
       { return this->VariadicClass<F>::GetField(); }
 };

template <typename ... As1, typename ... As2>
VariadicClass<As1...> * Filter(VariadicClass<As2...> in)
 {
   using unused = int[];

   auto ret = new VariadicClass<As1...>();

   (void)unused { 0, (ret->template Set<As1>(in.template Get<As1>()), 0)... };

   return ret;
 }


int main()
 {
   VariadicClass<int, bool, char> c1;

   c1.Set<int>(42);
   c1.Set<bool>(true);
   c1.Set<char>('Z');

   auto pC2 = Filter<int, bool>(c1);

   std::cout << pC2->Get<int>() << std::endl;
   std::cout << pC2->Get<bool>() << std::endl;

   delete pC2;
 }

离题未请求的建议:您正在使用C11,所以。。。尽量避免直接使用指针,而尽量使用智能指针(std::unique_ptrstd::shared_ptr等)。

 类似资料:
  • 5.7. 可变参数 参数数量可变的函数称为为可变参数函数。典型的例子就是fmt.Printf和类似函数。Printf首先接收一个的必备参数,之后接收任意个数的后续参数。 在声明可变参数函数时,需要在参数列表的最后一个参数类型之前加上省略符号“...”,这表示该函数会接收任意数量的该类型参数。 gopl.io/ch5/sum func sum(vals...int) int { total

  • 在第二章中,我们已经讲叙了基本的函数定义与调用方法,以及一些函数属性的作用。但 正如大多数编程语言一样,函数是如此普遍且重要的元素。因而本章继续讨论一些有关函 数的较为高级的用法。 5.1 可变参数 可变参数的意义 一般情况下,在定义函数时指定形参,在调用函数时传入实参,且参数个数必须要与定义 时指定的参数数量相等。但在一些情况下,我们将要实现的函数功能,它的参数个数可能 是不确定,或者有些参数是

  • 6. 可变参数 到目前为止我们只见过一个带有可变参数的函数printf: int printf(const char *format, ...); 以后还会见到更多这样的函数。现在我们实现一个简单的myprintf函数: 例 24.9. 用可变参数实现简单的printf函数 #include <stdio.h> #include <stdarg.h> void myprintf(const ch

  • 问题内容: 我正在努力查看将值传递给函数时使用哪种方法是否有明显的优势。下面的代码可能不是解释我要做出的决定的最佳示例,但我认为这是最容易理解的示例。 可变参数方法 数组参数法 两种技术中的哪一种是首选?如果是这样,为什么(速度,可靠性或只是易于阅读)?谢谢。 问题答案: 我认为没有速度差异。因为,在功能内部,您可以像一样使用。 我认为如果参数数量较少(例如小于5个),则因为易于阅读,可能是一个更

  • 问题内容: 有没有办法允许JavaScript中的函数使用“无限”的var? 例: 问题答案: 当然,只需使用对象即可。

  • Scala 函数 Scala 允许你指明函数的最后一个参数可以是重复的,即我们不需要指定函数参数的个数,可以向函数传入可变长度参数列表。 Scala 通过在参数的类型之后放一个星号来设置可变参数(可重复的参数)。例如: object Test { def main(args: Array[String]) { printStrings("Runoob", "Scala",