枚举像计算常数

dar*_*une 10 c++ constexpr c++17

实际上这个"问题"感觉非常简单.在做一些计算出的图标偏移时,我想出了以下方法:

namespace Icons {

  struct IconSet {
    constexpr IconSet(size_t base_offset) noexcept
      : base_offset_(base_offset), icon(base_offset * 3), iconSmall(icon + 1), iconBig(icon + 2) {
    }
    size_t icon;
    size_t iconSmall;
    size_t iconBig;

    size_t base_offset_;

    constexpr size_t next() const {
      return base_offset_ + 1;
    }
  };


  static constexpr IconSet flower = IconSet(0);
  static constexpr IconSet tree = IconSet(flower.next());
  static constexpr IconSet forest = IconSet(tree.next());
  static constexpr IconSet mountain = IconSet(forest.next());

 }
Run Code Online (Sandbox Code Playgroud)

现在可以编写一个Icons::tree.iconBig例子来获取该图标的计算偏移量.基本上,设计师可以更改图标 - 有时也可以添加/删除 - 但总是按惯例提供整个设置(正常,小和大).

如你所见,这种方法的问题是我必须做这个next()功能并重复使用它 - 正常的枚举不会有这个缺点.

我知道BOOST_PP和其他宏技巧,但我希望没有宏的东西 - 因为我觉得它不需要我然后我更喜欢我已经拥有的普通next()函数.另一种解决方案当然只是一个普通的枚举和一个计算函数,但这就是打破预先计算出来的目的.

因此,我正在寻找一种简单易用的解决方案,它将提供类似枚举的功能.它不必是编译时间,或者constexpr例如只是内联将使它更容易.

Bru*_*lie 9

这是一种可以使用的方法,基于编译时整数序列上的折叠表达式,通过索引实例化图标.结构化绑定可以为您提供单独命名的非静态,​​非constexpr变量.

内部的匿名命名空间Icons仅在这个翻译单元中显示这些定义,您可能想要也可能不想要.

编译器资源管理器链接,以便您自己探索代码选项.

#include <cstddef>
#include <array>
#include <utility>

namespace Icons {

struct IconSet {
    constexpr IconSet(size_t base_offset) noexcept 
      : base_offset_(base_offset), icon(base_offset * 3), iconSmall(icon + 1), iconBig(icon + 2) {
    }
    size_t icon;
    size_t iconSmall;
    size_t iconBig;

    size_t base_offset_;
};

template <std::size_t... Ints>
constexpr auto make_icons_helper(std::index_sequence<Ints...>) -> std::array<IconSet, sizeof...(Ints)> 
{
    return {IconSet(Ints)...};
}

template <size_t N>
constexpr auto make_icons()
{
    return make_icons_helper(std::make_index_sequence<N>{});
}

namespace {
    auto [flower, tree, forest, mountain] = make_icons<4>();
}

}

int main()
{
    return Icons::forest.iconSmall;
}
Run Code Online (Sandbox Code Playgroud)