我应该使用什么而不是模板化的枚举?

问题描述 投票:0回答:3

在我的代码中,我使用如下内容:

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.
    }

实现相当于这种模板化的优雅或者惯用的方式是什么?

c++ templates enums idiomatic
3个回答
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
投票

到目前为止我所做的是把我的枚举放在一个虚拟的持有者类中,可以模仿:

template <size_t N>
struct params
{
    enum {
        foo = sizeof(some_type_t) < 32 ? 1 : 2,
        bar = some_constexpr_function() - N,
        baz = foo + bar,
    };
}

但是我必须到处写params::fooparams::bar,这很乏味:

do_stuff_with(params::foo, params::bar)

代替

do_stuff_with(foo, bar);

0
投票

也许重载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)>{};
}

[live demo]

© www.soinside.com 2019 - 2024. All rights reserved.