【问题标题】:How can I read a variable number of values into a std::tuple?如何将可变数量的值读入 std::tuple?
【发布时间】:2013-04-27 05:52:09
【问题描述】:

我正在编写使用 BSD 文件描述符从管道读取值和向管道写入值的代码(使用 readwrite 调用)。这是一个简单的 IPC 系统的一部分,其中一个进程告诉另一个进程运行一个过程并返回一个结果。大多数时候只有一个返回值,但少数程序需要返回多个。为了避免必须为每个人创建一个新的struct,我想我可以使用std::tuples。

但是,我在创建一种将元素读入元组的通用方法方面收效甚微。我正在尝试单独读取这些值,因为这两个进程的位数不同(一个是 64 位,另一个是 32 位),并且我担心 tuple 结构中可能导致的不同对齐要求他们是不相容的。这是我尝试过的:

template<typename TTupleType>
struct TupleReader
{
    int fd;
    TTupleType& storage;

    TupleReader(int fd, TTupleType& storage) : fd(fd), storage(storage)
    { }

    template<size_t Index = std::tuple_size<TTupleType>::value - 1>
    inline void Read()
    {
        Read<Index - 1>(fd);
        auto& ref = std::get<Index>(storage);
        ::read(fd, &ref, sizeof ref);
    }
};

它显然无法编译,因为它试图实例化Read&lt;-1&gt;,而我使用的 STL 的实现将std::get&lt;-1&gt;static_assert 结合起来。但是,在类范围内特化模板化函数是非法的,但由于父 struct 也是模板化的,因此也不可能在外部特化该方法。 template&lt;typename TTupleReader&gt; void TupleReader&lt;TTupleType&gt;::Read&lt;0&gt;() 被认为是部分专业化。

所以看起来我对这种方法陷入了困境。有没有人想办法做到这一点?

【问题讨论】:

    标签: c++ c++11 metaprogramming


    【解决方案1】:

    您可以尝试使用索引:

    template< std::size_t... Ns >
    struct indices
    {
        typedef indices< Ns..., sizeof...( Ns ) > next;
    };
    
    template< std::size_t N >
    struct make_indices
    {
        typedef typename make_indices< N - 1 >::type::next type;
    };
    
    template<>
    struct make_indices< 0 >
    {
        typedef indices<> type;
    };
    
    struct sink
    {
        template<typename... T>
        sink(T&&...) {}
    };
    
    template<typename TTupleType>
    struct TupleReader
    {
        int fd;
        TTupleType& storage;
    
        TupleReader(int fd, TTupleType& storage) : fd(fd), storage(storage)
        { }
    
        template<size_t... Ns>
        inline void ReadImpl(const indices<Ns...>&)
        {
            sink { ::read(fd, &std::get<Ns>(storage),
                              sizeof(typename std::tuple_element<Ns,TTupleType>::type))... };
        }
    
        inline void Read()
        {
            ReadImpl(typename make_indices<std::tuple_size<TTupleType>::value>::type());
        }
    };
    

    【讨论】:

    • 非常聪明。我会试试的。
    【解决方案2】:

    您可以创建一个内部模板类TupleReader::Reader&lt;i&gt;,其中包含一个静态函数Read。然后,您可以根据需要为 &lt;i=0&gt; 案例部分专门化该内部类。然后TupleReader::Read&lt;n&gt; 可以实例化TupleReader::Reader&lt;n&gt; 并调用静态函数TupleReader::Reader&lt;n&gt;::Read

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-08-19
      • 2016-09-20
      • 2016-03-15
      • 2020-04-07
      • 1970-01-01
      • 2020-07-07
      • 1970-01-01
      • 2022-01-11
      相关资源
      最近更新 更多