假设我想从bitset< 1>实例化来自模板化类(类似于std :: bitset)的许多对象。 bitset< 10>。
for (size_t i = 1; i <= 10; ++i) {
std::bitset<i> my_bitset;
// do stuff with it...
}
显然这不会编译,因为我不是文字或constexpr
。
有办法做到这一点吗?我在脑海中想到一切模板元编程但我无法想象这一点。任何指针都赞赏。
答案 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";
}
};
#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特化。