gpt4 book ai didi

c++ - 类型敏感的元组访问者

转载 作者:搜寻专家 更新时间:2023-10-31 00:18:00 25 4
gpt4 key购买 nike

假设我有一个 std::tuple 由如下类型组成

struct A {
static void tip();
};

struct B {
static void tip();
};

struct Z {
};

std::tuple<const A&,const B&,const Z&> tpl;

是的,我需要单独的AB。 (::tip() 的实现因类型而异。)我尝试实现的是类型敏感的“访问者”,它从头到尾遍历元组。在访问 T 类型的特定元素时,应根据 T 是否具有 ::tip() 方法来调用函数。在上面的简单示例中,只有 AB 实现了 ::tip()Z 没有。因此,迭代器应该为使用 ::tip() 方法的类型调用两次函数,并调用另一个函数一次。

这是我想出的:

template< int N , bool end >
struct TupleIter
{
template< typename T , typename... Ts >
typename std::enable_if< std::is_function< typename T::tip >::value , void >::type
static Iter( const T& dummy , const std::tuple<Ts...>& tpl ) {
std::cout << "tip\n";
std::get<N>(tpl); // do the work
TupleIter<N+1,sizeof...(Ts) == N+1>::Iter( std::get<N+1>(tpl) , tpl );
}

template< typename T , typename... Ts >
typename std::enable_if< ! std::is_function< typename T::tip >::value , void >::type
static Iter( const T& dummy , const std::tuple<Ts...>& tpl ) {
std::cout << "no tip\n";
std::get<N>(tpl); // do the work
TupleIter<N+1,sizeof...(Ts) == N+1>::Iter( std::get<N+1>(tpl) , tpl );
}
};


template< int N >
struct TupleIter<N,true>
{
template< typename T , typename... Ts >
static void Iter( const std::tuple<Ts...>& tpl ) {
std::cout << "end\n";
}
};

我在迭代器位置使用元素类型的 dummy 实例,并通过 enable_if 决定调用哪个函数。不幸的是,这不起作用/不是一个好的解决方案:

  1. 编译器提示递归实例化
  2. const T& dummy 不是一个干净的解决方案

我想知道 enable_if 是否是做出决定的正确策略,以及如何递归迭代 std::tuple 捕获第一种类型并保留所有类型剩余参数处于重要状态。通读How to split a tuple?但它不做任何决定。

如何在 C++11 中以正确且可移植的方式实现这样的事情?

最佳答案

好吧,这比我预期的要难,但是this有效。

一些你做错的/我修改的:

  1. 你不能评估这个:std::is_function< typename T::tip >::value , 自 T::tip不是一种类型。即使可以对此进行评估,当 T::tip 时会发生什么?不存在?替换仍然会失败。
  2. 由于您使用 const 引用作为元组的内部类型,因此您必须先清理它们,然后再尝试在其中找到 tip 成员。我所说的清理是指删除 const 并删除引用。
  3. 那个虚拟类型的东西不是个好主意,没有必要使用那个参数。您可以使用 std::tuple_element 实现相同的目的,它从元组中检索第 i 个类型。
  4. 我修改了TupleIter的模板参数如下,这意味着:

TupleIter 处理大小为 n 的元组内的第 index 个类型”。

template<size_t index, size_t n> 
struct TupleIter;

整个代码是这样的:

#include <tuple>
#include <iostream>
#include <type_traits>

struct A {
static void tip();
};

struct B {
static void tip();
};

struct Z {
};

// Indicates whether the template parameter contains a static member named tip.
template<class T>
struct has_tip {
template<class U>
static char test(decltype(&U::tip));

template<class U>
static float test(...);

static const bool value = sizeof(test<typename std::decay<T>::type>(0)) == sizeof(char);
};

// Indicates whether the n-th type contains a tip static member
template<size_t n, typename... Ts>
struct nth_type_has_tip {
static const bool value = has_tip<typename std::tuple_element<n, std::tuple<Ts...>>::type>::value;
};

// Generic iteration
template<size_t index, size_t n>
struct TupleIter
{
template< typename... Ts >
typename std::enable_if< nth_type_has_tip<index, Ts...>::value , void >::type
static Iter(const std::tuple<Ts...>& tpl)
{
std::cout << "tip\n";
TupleIter<index + 1, n>::Iter(tpl );
}

template< typename... Ts >
typename std::enable_if< !nth_type_has_tip<index, Ts...>::value , void >::type
static Iter(const std::tuple<Ts...>& tpl) {
std::cout << "no tip\n";
TupleIter<index + 1, n>::Iter(tpl );
}
};

// Base class, we've reached the tuple end
template<size_t n>
struct TupleIter<n, n>
{
template<typename... Ts >
static void Iter( const std::tuple<Ts...>& tpl ) {
std::cout << "end\n";
}
};

// Helper function that forwards the first call to TupleIter<>::Iter
template<typename... Ts>
void iterate(const std::tuple<Ts...> &tup) {
TupleIter<0, sizeof...(Ts)>::Iter(tup);
}

int main() {
A a;
B b;
Z z;
std::tuple<const A&,const B&,const Z&> tup(a,b,z);
iterate(tup);
}

关于c++ - 类型敏感的元组访问者,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11843684/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com