Is there an existing name for this type and functi

2020-05-19 06:04发布

问题:

There are 2 hard problems in computer science: cache invalidation, naming things and off-by-one errors.

This is about the 2nd problem: naming things.

I'm looking if this technique or type has been used somewhere else already and has a name. dichotomy is an ok name, but bools_at_compile_time is a horrible one.

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 is a variant between true and false. Its runtime representation is 0 or 1.

What this lets you do is:

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
}

Is there a name for dichotomy_t or the more general bools_at_compile_time technique? I'm looking for a name that is well known in any community (even a non-C++ one), even a verb that describes "taking a runtime value and creating a switch and a set of compile time value in generated code to pick between" better than a sentence.

Live example

A good answer would include the name, citations/quotes describing what that name means, examples of that named thing in use in the other context, and evidence that this name is equivalent to or inclusive of the above type/value and function.

(It may help to find a name the generalization of this would be an enum instead of a bool, which has a fixed number of known states, and a switch/case map that converts the runtime value into a compile-time constant in each case clause.)

回答1:

I do not know of any existing names for this pattern, but if you take a good look at how the STL is naming things, you can use name close enough to make your code explicit.

I also liked the dispatcher_t idea from @Jarod42 , I think it is more generic than dichotomy_t or n_chotomy_t.

dichotomy() could be called make_variant(b). Since it will return the std::variant value of a boolean given in argument. Much like std::make_tuple makes a tuple from multiple arguments.

I would suggest to replace bools_at_compile_time by static_eval. Much like static_assert makes an assertion at compile time.

Not that if eval is not the correct adjective for your use case you can easily adapt it 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";
}


回答2:

Generation of specialized version of a function is called cloning. (see Procedure Cloning). The term clone is used to name the specialized function generated by the optimizer during constant propagation (see gcc doc).

The set of specialized functions generated by std::visit could be named clone set.

This set is generated for all combinations of argument value. This term combination let us suppose that the set of possible value of each argument is finite.

So we could have a long name for the set of clones such as, set of clones for all combination of argument values. An other option more obscure but shorter could be combinatorial clone set.

As already pointed out, the action of selecting the right function to call in term of the argument could be called dispatch.

So I would propose combinatiorial_clone_set_dispatch or dispatch_in_combinatorial_clone_set ...



回答3:

As I am unaware of a similar implementation, I'll just go type by type with bikeshed colors.


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

This is pretty self-explanatory, as it's a variant that can store one or the other of the std::integral_constants for true or false. It's kind of a bool, but bool_t is likely to cause confusion. An alternative is boolean_variant, but that may be too verbose.


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

I started with convert_bool, but that's a bit too generic. to_boolean_t is more expressive. make_boolean_t is also a possibility, as it is basically a boolean_t factory function. Note: I previously chose to_constexpr_boolean, but that's unnecessarily verbose.


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

I chose static_eval here as I like Clonk's reasoning, but "static" has contextual meaning in C++, so alternatives are (in no order of importance):

  • boolean_visit
  • static_visit
  • constexpr_eval
  • constexpr_visit


回答4:

You issue was: (bold mine)

I'm looking for a name that is well known in any community (even a non-C++ one), even a verb that describes "taking a runtime value and creating a switch and a set of compile time value in generated code to pick between" better than a sentence.

There is, but only if you will adopt it from a related field of science:

The U.S. National Electrical Code (NEC) defines a switchboard as "a large single panel, frame, or assembly of panels on which are mounted, on the face, back, or both, switches, over-current and other protective devices, buses, and usually instruments". The role of a switchboard is to allow the division of the current supplied to the switchboard into smaller currents for further distribution and to provide switching, current protection and (possibly) metering for those various currents. In general, switchboards may distribute power to transformers, panelboards, control equipment, and, ultimately, to individual system loads.

Adopting this thinking, you would simply call it switches.

I will also add that it is quite unusual to specify (ie. repeat) the storage type or cv-qualifier, etc. in type/variable names - even when not directly visible you would usually leave that as implicit - unless it really needs to be emphasized.



回答5:

Maybe staticCastValue? As in you are casting a dynamic(runtime) value to a static value. Can be used with templates or overloads for different types.

Or maybe assertInmutable? As in you are converting a mutable type into an inmutable one.

Or perhaps expressConstantly? As in you are expressing the same value but in constant form. A form similar to constexpr.

A wild one: staticBifurcate? As in theres two things to choose from, thus a bifurcation is there.

bifurcate verb /ˈbʌɪfəkeɪt/ 1. divide into two branches or forks. "just below Cairo the river bifurcates"

Or finally convertToConstExpr? Explicitly saying that the value will be converted to something akin or compatible with a constexpr.