该类型和功能是否已有名称?

时间:2019-05-03 19:17:44

标签: c++ boolean c++17 variant

计算机科学中有两个难题:缓存失效,事物命名和一次性错误。

这是关于第二个问题:命名事物。

我正在寻找这种技术或类型是否已经在其他地方使用过并且有名称。 dichotomy是个不错的名字,但是bools_at_compile_time是个可怕的名字。

using dichotomy_t = std::variant<std::false_type, std::true_type>;
// (or a struct that inherits from that, and overloads operator bool())

constexpr dichotomy_t dichotomy( bool b ) {
  if (b) return std::true_type{};
  return std::false_type{};
}
template<class F, class...Bools>
constexpr auto bools_at_compile_time( F&& f, Bools...bools ) {
  static_assert( (std::is_same<Bools, bool>{} && ...) );
  return std::visit( std::forward<F>(f), dichotomy(bools)... );
}

dichotomy_t是true和false之间的变体。其运行时表示为01

这让您可以做的是:

auto foo( bool x, bool y ) { // <-- x and y are run-time bools here
  auto func = [&](auto x, auto y) {
    return some_template<x,y>(); // <-- x and y are compile-time bools here
  };
  return bools_at_compile_time( func, x, y ); // <-- converts runtime to compile time bools
}

是否有dichotomy_t或更通用的bools_at_compile_time技术的名称?我正在寻找一个在任何社区(甚至是非C ++社区)中都广为人知的名称,甚至是描述“获取运行时值并在生成的代码中创建一个开关和一组编译时间值以供选择的动词”。 “胜过一句话。

Live example

一个好的答案应该包括名称,描述该名称含义的引文/引号,该名称在其他情况下使用的示例以及该名称等同于或包含上述类型/值和功能的证据。

(这可能有助于找到一个名称,将其概括为enum而不是bool,后者具有固定数量的已知状态,并且开关/案例映射可将每个case子句中将运行时值转换为编译时常量。)

5 个答案:

答案 0 :(得分:10)

我不知道该模式的任何现有名称,但是如果您很好地了解STL如何命名事物,则可以使用足够接近的名称使代码明确。

我也喜欢@ Jarod42的dispatcher_t想法,我认为它比dichotomy_tn_chotomy_t更通用。

dichotomy()可以称为make_variant(b)。因为它将返回参数中给定的布尔值的std::variant值。就像std::make_tuple由多个参数组成一个元组。

我建议将bools_at_compile_time替换为static_eval。就像static_assert在编译时进行断言一样。

如果eval对于您的用例而言不是正确的形容词,则可以轻松地对其进行调整static_*

#include <type_traits>
#include <variant>
#include <utility>

using dichotomy_t = std::variant<std::false_type, std::true_type>;
// (or a struct that inherits from that, and overloads operator bool())

constexpr dichotomy_t make_variant( bool b ) {
  if (b) return std::true_type{};
  return std::false_type{};
}
template<class F, class...Bools>
constexpr auto static_eval( F&& f, Bools...bools ) {
  static_assert( (std::is_same<Bools, bool>{} && ...) );
  return std::visit( std::forward<F>(f), make_variant(bools)... );
}

template<bool x, bool y>
auto some_template() {
    return x || y;
}

auto foo( bool x, bool y ) { // <-- x and y are run-time bools here
  auto func = [&](auto x, auto y) {
    return some_template<x,y>(); // <-- x and y are compile-time bools here
  };
  return static_eval( func, x, y ); // <-- converts runtime to compile time bools
}

#include <iostream>

int main() {
    std::cout << foo( true, true ) << "\n";
}

答案 1 :(得分:4)

函数专业版本的生成称为 cloning 。 (请参见Procedure Cloning)。术语 clone 用于命名优化器在恒定传播期间生成的专用功能(请参见gcc doc)。

std::visit生成的一组专用函数可以命名为 clone set

此集合是为所有combinations个参数值生成的。这个术语 combination 让我们假设每个参数的可能值是有限的。

所以我们可以为克隆集起一个长名称,例如,对于所有参数值组合的克隆集组合克隆集

正如已经指出的那样,选择根据参数调用的正确函数的动作可以称为 dispatch

所以我会建议combinatiorial_clone_set_dispatchdispatch_in_combinatorial_clone_set ...

答案 2 :(得分:2)

由于我不知道类似的实现方式,所以我将逐字逐句地键入带有自行车遮挡的颜色。


using boolean_t = std::variant<std::false_type, std::true_type>;

这是很不言自明的,因为它是一个变体,可以存储std::integral_constant中的一个或多个,以表示是非。有点像bool,但是bool_t可能会引起混乱。另一种选择是boolean_variant,但这可能太冗长了。


constexpr boolean_t to_boolean_t( bool b ) {
  if (b) return std::true_type{};
  return std::false_type{};
}

我从convert_bool开始,但这有点太笼统了。 to_boolean_t更具表现力。 make_boolean_t也是可能的,因为它基本上是boolean_t工厂函数。注意:我以前选择了to_constexpr_boolean,但这是不必要的冗长。


template<class F, class...Bools>
constexpr auto static_eval( F&& f, Bools...bools ) {
  static_assert( (std::is_same<Bools, bool>{} && ...) );
  return std::visit( std::forward<F>(f), to_boolean_t(bools)... );
}

我在这里选择static_eval是因为我喜欢Clonk的推理,但是“静态”在C ++中具有上下文含义,因此替代方法是(按重要性排序):

  • boolean_visit
  • static_visit
  • constexpr_eval
  • constexpr_visit

答案 3 :(得分:1)

您的问题是:(粗体字)

  

我正在寻找一个在任何社区(甚至是   非C ++代码),甚至是描述“ 采用运行时值和   在生成的代码中创建一个开关和一组编译时间值以   胜过一个句子。

有,但是只有当您从相关的科学领域采用它时:

  

美国国家电气法规(NEC)将配电盘定义为“   大型单个面板,框架或已安装面板的组件,   在正面,背面或两者上,开关,过电流和其他   保护装置,公共汽车和通常的仪表”。   配电盘应允许分配给   将配电板转换成较小的电流,以便进一步分配和   提供开关,电流保护和(可能)计量   那些各种各样的潮流。通常,配电盘可以分配电源   到变压器,配电盘,控制设备,最后是   单个系统负载。

采用这种思想,您可以简单地将其称为开关

我还要补充一点,在类型/变量名称中指定(即 repeat )存储类型或cv限定符等是非常不寻常的-即使当您无法直接看到它们时,将其保留为隐式-除非确实需要强调。

答案 4 :(得分:0)

也许是staticCastValue? 就像您将动态(运行时)值转换为静态值一样。 可以与不同类型的模板或重载一起使用。

或者是assertInmutable? 就像您将可变类型转换为不变类型一样。

或者恒定表达? 就像您在表达相同的值,但以常数形式。 类似于constexpr的形式。

一个疯狂的人: staticBifurcate? 既然有两种选择,那么分叉就在那里。

分叉 动词 / ˈbʌɪfəkeɪt / 1。 分为两个分支或分支。 “在开罗下面,这条河分叉了”

或者最后是convertToConstExpr? 明确地说,该值将转换为类似于constexpr或与constexpr兼容的值。