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

时间:2017-12-16 10:11:33

标签: c++ templates enums idiomatic

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

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

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

3 个答案:

答案 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::fooparams::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)>{};
}

[live demo]