我应该使用什么而不是模板化的枚举?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了我应该使用什么而不是模板化的枚举?相关的知识,希望对你有一定的参考价值。
在我的代码中,我使用如下内容:
enum {
foo = sizeof(some_type_t) < 32 ? 1 : 2,
bar = some_constexpr_function() - N,
baz = foo + bar,
// etc.
}
对于一堆编译时常量我想确保没有运行时存储;我有一些使用这些常量的函数。 N是我们从别处得到的一些常数。
现在我想拿出我的代码并将其模板化:N不再是全局常量,而是数字模板参数。现在,如果我这样做:
template <size_t N> f()
{
enum {
foo = sizeof(some_type_t) < 32 ? 1 : 2,
bar = some_constexpr_function() - N,
baz = foo + bar,
// etc.
}
}
那会有用;但是 - 这限制了我在一个函数中使用这些常量;我想要几个。在C ++中,我们不能拥有
template <size_t N>
enum {
foo = sizeof(some_type_t) < 32 ? 1 : 2,
bar = some_constexpr_function() - N,
baz = foo + bar,
// etc.
}
实现相当于这种模板化的优雅或者惯用的方式是什么?
答案
正如你在评论中被告知的那样,我没有看到一点坚持将这些命名常量置于一个枚举下。在一个命名空间范围内只有一堆constexpr
变量。您可以获得相同的净效果:
namespace constants {
namespace detail {
using underlying_t = int;
}
template<size_t N>
constexpr detail::underlying_t foo = sizeof(some_type_t) < 32 ? 1 : 2;
template<size_t N>
constexpr detail::underlying_t bar = some_constexpr_function() - N;
template<size_t N>
constexpr detail::underlying_t baz = foo<N> + bar<N>;
}
它们都是constexpr
,因此它们很容易运行时间常数,如果需要,您可以在一个地方控制基础类型。此外,您可以通过完全限定的ID访问它们,也可以使用using指令将它们全部带入。
另一答案
到目前为止我所做的是把我的枚举放在一个虚拟的持有者类中,可以模仿:
template <size_t N>
struct params
{
enum {
foo = sizeof(some_type_t) < 32 ? 1 : 2,
bar = some_constexpr_function() - N,
baz = foo + bar,
};
}
但是我必须到处写params::foo
,params::bar
,这很乏味:
do_stuff_with(params::foo, params::bar)
代替
do_stuff_with(foo, bar);
另一答案
也许重载comma constexpr会满足你的需求?
#include <utility>
enum params {
foo = 1,
bar = 2,
baz = 3
};
struct some_type_t { };
constexpr std::size_t some_constexpr_function() {
return 0;
}
constexpr std::size_t operator ,(params P, std::size_t N) {
switch (P) {
case foo:
return sizeof(some_type_t) < 32 ? 1 : 2;
case bar:
return some_constexpr_function() - N;
case baz:
return (foo, N) - (bar, N);
}
return 0;
}
template <std::size_t>
struct example { };
int main() {
example<(baz, 2)>{};
}
以上是关于我应该使用什么而不是模板化的枚举?的主要内容,如果未能解决你的问题,请参考以下文章