【发布时间】:2014-06-08 20:16:14
【问题描述】:
如何将转换后的 integer_sequence(或类似的,因为我的目标是 C++11)插入可变参数模板参数?
例如,我有一个代表一组位标志的类(如下所示)。它是使用嵌套类制作的,因为同一个类不能有两个可变参数模板参数。它将像typedef Flags<unsigned char, FLAG_A, FLAG_B, FLAG_C>::WithValues<0x01, 0x02, 0x04> MyFlags 一样使用。通常,它们将与 2 的幂的值一起使用(尽管并非总是如此,在某些情况下会进行某些组合,例如可以想象一组标志,如 Read=0x1、Write=0x2 和 ReadWrite=0x3 =0x1|0x2)。我想提供一种方法来做typedef Flags<unsigned char, FLAG_A, FLAG_B, FLAG_C>::WithDefaultValues MyFlags。
template<class _B, template <class,class,_B> class... _Fs>
class Flags
{
public:
template<_B... _Vs>
class WithValues :
public _Fs<_B, Flags<_B,_Fs...>::WithValues<_Vs...>, _Vs>...
{
// ...
};
};
我尝试了以下但没有成功(放置在 Flags 类中,在 WithValues 类之外):
private:
struct _F {
// dummy class which can be given to a flag-name template
template <_B _V> inline constexpr
explicit _F(std::integral_constant<_B, _V>) { } };
// we count the flags, but only in a dummy way
static constexpr unsigned _count = sizeof...(_Fs<_B, _F, 1>);
static inline constexpr
_B pow2(unsigned exp, _B base = 2, _B result = 1) {
return exp < 1 ?
result :
pow2(exp/2,
base*base,
(exp % 2) ? result*base : result);
}
template <_B... _Is> struct indices {
using next = indices<_Is..., sizeof...(_Is)>;
using WithPow2Values = WithValues<pow2(_Is)...>;
};
template <unsigned N> struct build_indices {
using type = typename build_indices<N-1>::type::next;
};
template <> struct build_indices<0> {
using type = indices<>;
};
//// Another attempt
//template < _B... _Is> struct indices {
// using WithPow2Values = WithValues<pow2(_Is)...>;
//};
//template <unsigned N, _B... _Is> struct build_indices
// : build_indices<N-1, N-1, _Is...> { };
//template < _B... _Is> struct build_indices<0, _Is...>
// : indices<_Is...> { };
public:
using WithDefaultValues =
typename build_indices<_count>::type::WithPow2Values;
当然,我愿意为整个情况提供任何其他替代方案(支持同一模板集中的标志名称和值等)。
我在 ideone 中包含了一个“工作”示例:http://ideone.com/NYtUrg - “工作”是指在不使用默认值的情况下编译良好,但使用默认值失败(有一个 #define 在它们之间切换)。
谢谢!
【问题讨论】:
-
不要使用以下划线开头的标识符,然后是大写字母。这些是为实现(编译器和标准库)保留的。
-
谢谢。您是否还暗示下划线 - 小写字母好吗?我使用下划线来避免标志名称与标志类的“内部”使用名称发生冲突的问题。
-
@coderforlife 至于下划线,只需将它们向后放置以避免违反标准规则,例如
B_而不是_B。这很容易:P ... -
没有阅读整篇文章。只需评论:
It is made using a nested-class because you cannot have two variadic template arguments for the same class。实际上你可以使用元组:template <class... Args1, class... Args2> class X<std::tuple<Args1...>, std::tuple<Args2...>。同样,没有阅读问题,对此感到抱歉,但这也许可以帮助您简化设计。 -
这是一个有趣的想法,但是它在这里不起作用,因为一个可变参数模板不是类/类型名包而是一个整体包(因此解包一个整数序列)。我想可以制作一个类似元组的类来支持它......
标签: c++ templates c++11 variadic-templates