在我的代码中,我使用如下内容:
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.
}
实现相当于这种模板化的优雅,或者也许是惯用的方式是什么?
答案 0 :(得分:4)
就像你在评论中被告知的那样,我没有看到一点坚持将这些命名的常量置于一个枚举下。在单个命名空间范围内只有一堆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指令将它们全部带入。
答案 1 :(得分:1)
我到目前为止所做的是将我的枚举放入虚拟持有人类中,可以模仿:
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);
答案 2 :(得分:0)
也许重载comma constexprly会满足您的需求?
#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)>{};
}