c ++以编程方式创建模板化对象

时间:2013-11-20 07:52:17

标签: c++ templates template-meta-programming

假设我想从bitset< 1>实例化来自模板化类(类似于std :: bitset)的许多对象。 bitset< 10>。

for (size_t i = 1; i <= 10; ++i) {
  std::bitset<i> my_bitset;
  // do stuff with it...
}

显然这不会编译,因为我不是文字或constexpr

有办法做到这一点吗?我在脑海中想到一切模板元编程但我无法想象这一点。任何指针都赞赏。

4 个答案:

答案 0 :(得分:3)

如您所知,不可能将运行时变量用作模板参数;但是,如果你知道在编译时使用的值列表,那么你确实可以有办法为这个列表的每个元素调用测试。

template <template <size_t> class F>
void run() {}

template <template <size_t> class F, size_t H, size_t... Tail>
void run() { F<H>()(); run<F, Tail...>(); }

然后只需定义F

template <size_t N>
struct BitSetPlay {
    void operator()() {
        std::bitset<N> b;
        b.flip();
        std::cout << b.to_ulong() << "\n";
    }
};

Putting it altogether

#include <bitset>
#include <iostream>

template <template <size_t> class F>
void run() {}

template <template <size_t> class F, size_t H, size_t... Tail>
void run() { F<H>()(); run<F, Tail...>(); }

template <size_t N>
struct BitSetPlay {
    void operator()() {
        std::bitset<N> b;
        b.flip();
        std::cout << b.to_ulong() << "\n";
    }
};

int main() {
    run<BitSetPlay, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u, 10u>();
    return 0;
}

注意:这假定了一个可能不连续的列表,如果它是你想要的范围,那么只需跟踪边界就可以没有可变参数模板。

答案 1 :(得分:2)

这是不可能的,因为模板只是一个编译时的概念。您不能使用运行时数据来声明模板化实例。

模板参数必须是类型或编译时常量。

答案 2 :(得分:2)

像(未经测试)的东西:

template<int N>
struct InstantBS
{
    std::bitset<N> bs;
    InstantBS<N-1> next;
};

template<>
struct InstantBS<0>
{
};

template struct InstantBS<10>; //instantiate bitset<1> to bitset<10>

更新:嗯,我已经测试过了,它不起作用!问题是InstantBS的成员未被隐式实例化。遗憾的是,显式实例化必须在命名空间级别进行,因此您无法强制显式实例化来自另一个显式实例化。不幸的是,模板命名空间还没有发明......

我能想到的最接近的想法就是这样,对你需要的bitset的任何成员进行手动即时:

template<int N>
struct InstantBS
{
    void DoThings()
    {
        std::bitset<N> bs;
        bs.set();
        bs.reset();
        bs.flip();
        //any other operation you want to instantiate

        InstantBS<N-1> next;
        next.DoThings();
    }
};

template<>
struct InstantBS<0>
{
    void DoThings()
    {
    }
};
template struct InstantBS<10>; //instantiate bitset<1> to bitset<10>, more or less

您可以检查bitsets的requestet成员是否实际实例化了:

$ g++ -c test.cpp
$ objdump -t test.o | c++filt | grep bitset

答案 3 :(得分:0)

查看文档: bitset的大小在编译时固定(由其模板参数确定)。对于也优化空间分配并允许动态调整大小的类,请参阅vector(vector)的bool特化。