C++ 可变模板展开-展开除第i个条目以外的所有条目

C++ 可变模板展开-展开除第i个条目以外的所有条目,c++,c++20,c++14,C++,C++20,C++14,有没有办法从类型扩展中删除其中一个类型 我们以tuple为例 void foo() { tuple<int, double, string> t; // some facility to expand except the i-th type: expand_except_ith<0>(t); // returns tuple<double, string> expand_except_ith<1>(t)

有没有办法从类型扩展中删除其中一个类型

我们以tuple为例

void foo() {
     tuple<int, double, string> t;
     // some facility to expand except the i-th type:
     expand_except_ith<0>(t);   // returns tuple<double, string>
     expand_except_ith<1>(t);   // returns tuple<int, string>
}
void foo(){
元组t;
//除第i种类型外,需要扩展的一些设施:
展开除第(t)列之外的第(u);//返回元组
展开除第(t)列之外的第(u);//返回元组
}
#包括
#包括
#包括
#包括
#包括
命名空间详细信息
{
样板
结构索引\序列\辅助对象:公共索引\序列\辅助对象
{
};
样板
结构索引\序列\辅助对象:公共索引\序列\辅助对象
{
};
样板
结构索引\u序列\u辅助对象
{
使用type=std::index\u序列;
};
}//名称空间详细信息
样板
使用make_index_sequence_except=typename details::index_sequence_helper::type;
样板
按顺序自动生成元组(常量元组和t,标准::索引序列)
{
返回std::make_tuple(std::get(t)…);
}
样板
自动展开(常量std::tuple&t)
{
返回make_tuple_by_seq(t,make_index_sequence_,除了{});
}
int main()
{
std::元组t;
//除第i种类型外,需要扩展的一些设施:
auto t0=expand_except_ith(t);//返回元组
auto t1=expand_except_ith(t);//返回元组
auto t2=expand_except_ith(t);//返回元组
std::cout以下是一个简短版本:


因为它不允许您使用非constexpr对象调用成员函数,即使该函数不使用
this
。即使在中,clang也可以正常工作。我认为这是一个标准的歧义,后来被清除了。

这里有一个简短的解决方案,用于删除由类型持有者类中的索引表示的单个类型(例如,
std::tuple
boost::mp11::mp_list
等)

#包括
#包括
#包括
样板
constexpr自动展开,除第i个(TList)外{

静态断言(N这是严格意义上的C++11吗?@GuillaumeRacicot不,不是严格意义上的C++11,更像是C++1xI将实时示例中的编译器更改为g++并且代码不再生成。我喜欢这个解决方案的想法,并且正在尝试在我使用的编译器中编译它。我对扩展有一个问题。让我们以after为例。它采用函数f,and将索引包扩展为其参数——f(0,1,2)。std::get(元组)将这些索引作为模板参数,而不是函数参数。请解释f(std::integral_constant…)与std::get()的关系?@candy将
get
替换为
get
并与
Bs
类似以使其工作。它抱怨constepr运算符的大小,gcc c c++14模式是ststSting它不是constepr,因为对象不是。(运算符不使用它,所以clang认为它是constepr)后来的标准明确了clang是正确的iirc。@candy它确实是
f(0_k,1_k,{n-1}k)
其中
x_k
是一个整数常量,它以其类型对值x进行编码。即使
*这不是constexpr(但不是在gcc c c++14模式下)。
索引器(f)
调用
f(0,1,2)
。然后在
f
中调用
indexer
,并将其传递给
g
,它将
0…size-1-3
作为常量。然后我们展开两个包,将N+1添加到第二个,得到元组元素
0,1,2
,然后传递到
4,5,6,7
。我们将其传递到元组中,并返回所有结果。
template<std::size_t...Is>
auto indexer( std::index_sequence<Is...> ) {
  return [](auto && f) {
    return f( std::integral_constant<std::size_t, Is>{}... );
  };
}
template<std::size_t N>
auto indexer() {
  return indexer( std::make_index_sequence<N>{} );
}

template<std::size_t N, class T>
auto except_nth( T&& t ) {
  constexpr auto size = std::tuple_size< std::decay_t<T> >{};
  static_assert( N < size, "No skipping past the end" );
  auto before = indexer<N>();
  auto after = indexer< size-N-1 > ();
  return before( [&]( auto...As ) {
    return after( [&]( auto...Bs ) {
      return std::make_tuple( std::get<As>(std::forward<T>(t))..., std::get<N+1+Bs>(std::forward<T>(t))... );
    } );
  });
}
      return std::make_tuple( std::get<decltype(As){}>(std::forward<T>(t))..., std::get<N+1+decltype(Bs){}>(std::forward<T>(t))... );