我正在研究使用BSD文件描述符从管道读取和写入值的代码(使用read
和write
调用)。这是一个简单的IPC系统的一部分,其中一个进程告诉另一个进程运行一个过程并返回一个结果。大多数情况下,只有一个返回值,但是一些程序需要返回多个返回值。为了避免为每个人执行新的struct
,我认为我可以使用std::tuple
s。
但是,我创造了一种将元素读入元组的通用方法,但收效甚微。我试图单独读取值,因为这两个进程没有相同的位(一个是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<-1>
并且STL的实现使用std::get<-1>
来捕获static_assert
。但是,在类范围中专门化模板化函数是非法的,但由于父struct
也是模板化的,因此不可能在外部专门化该方法。 template<typename TTupleReader> void TupleReader<TTupleType>::Read<0>()
被视为部分专业化。
所以看起来我对这种方法陷入了困境。有没有人看到这样做的方法?
答案 0 :(得分:4)
您可以尝试使用索引:
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());
}
};
答案 1 :(得分:0)
您可以创建包含单个静态函数TupleReader::Reader<i>
的内部模板类Read
。然后,您可以根据需要为<i=0>
案例部分专门化内部类。然后,TupleReader::Read<n>
可以实例化TupleReader::Reader<n>
并调用静态函数TupleReader::Reader<n>::Read
。