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

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

[live demo]

以上是关于我应该使用什么而不是模板化的枚举?的主要内容,如果未能解决你的问题,请参考以下文章

枚举器而不是类实例化的构造函数?

在序列化时,我应该更改什么设置来获取枚举的int值而不是其字符串表示形式? [重复]

如何使用在同一类的基模板中的类中声明的枚举

为啥使用常量而不是枚举?

显示/隐藏片段而不是替换

什么时候应该使用列表而不是 ICollection 或 IEnumerable? [关闭]