在c++ 11中迭代模板类

Iterate over template classes in c++ 11

本文关键字:迭代 c++      更新时间:2023-10-16

假设,我有这样定义的类:

template<unsigned int N>
class A { ... }

问题是如何用N遍历这些类?

for(unsigned int i = 0; i < 10; ++i) {
    A<i>().doStuff();
}

可能c++ 11中有一些新特性或者对contrexp的一些很酷的使用。

下一个问题是:如果可能的话——如何存储这样的类?

我知道它在编译时起作用。假设,我有多达10个这样的全局类,它们只在n上不同。例如:

A<1> first;
A<2> second;
A<42> third;
A<1034> fourth;

假设,我应该叫N比我的值大的那个。如果没有迭代的机会,那么我必须写一个很长的If -else结构。

void doAppropriateStuff(int value) {
    if (value < 1) {
        first.doStuff();
    } else if (value < 2) {
        second.doStuff();
    } else if (value < 42) {
        third.doStuff();
    } else if (value < 1034) {
        fourth.doStuff();
    } else {
      ...
    }
}

希望,问题变得更清楚了。当我在谷歌上搜索时,这是不可能的,我明白为什么。只寄希望于c++ 11和SO社区。谢谢。

for循环显然是不可能的,因为它是在运行时运行的,模板参数需要是编译时常量。你可以这样做。

这些是用于构造整型序列作为模板实参包的实用程序类:

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;
};

执行工作的函数:

#include <initializer_list>
template<size_t... Is>
void foo(indices<Is...>)
{
    auto list = { (A<Is>().doStuff(), 0)... };
}

然后像这样调用函数:

foo(make_indices<10>::type());

如果您不想依赖c++14中的integer_sequence,这是一个更简单的解决方案:

#include <iostream>
template<unsigned int N>
struct A {
    void dostuff() const { std::cout << N << " "; }
};
template < int N > void run();
template <>        void run<-1>() {}
template < int N > void run() {
    run<N-1>();
    A<N>{}.dostuff();
}
int main() {
    run<10>();
}

编辑:关于你的问题更新,你可以这样做,如果你将对象存储在一个元组中,见这里:

#include <iostream>
#include <tuple>
template<unsigned int N>
struct A {
    unsigned int getN() const { return N; }
    void dostuff() const { std::cout << N << " "; }
};
auto globals = std::make_tuple( A<3>{}, A<7>{}, A<10>{}, A<200>{} );
template <int idx> void run( int v );
template <>        void run<std::tuple_size<decltype(globals)>::value>( int ) {}
template <int idx = 0> void run( int v ) {
    auto & a = std::get<idx>(globals);
    if ( v < a.getN() ) {
        a.dostuff();
    } else {
        run<idx+1>(v);
    }
}
int main() {
    for( int i = 0; i<20; ++i)
        run( i );
}

您可以使用模板专门化:

template <unsigned int N> struct ADoer
{
    static void go() { A<N>().doStuff(); ADoer<N - 1>::go(); }
};
template <> struct ADoer<0>
{
    static void go() { }
};