Say I have a variable amount of arguments which I want to multiply together. The first way I think of is a recursive algorithm:
template<typename Head>
u64 Multiply(Head head) const
{
return head;
}
template<typename Head, typename... Tail>
u64 Multiply(Head head, Tail... tail) const
{
return head * Multiply(tail...);
}
But then I saw this trick:
// u32 and u64 are 32 and 64 bit unsigned integers.
template<typename... T>
u64 Multiply(T... args)
{
u64 res = 1;
for (const u32& arg: {args...})
res *= arg;
return res;
}
The second one appears way nicer to me. Easier to read. However, how does this act on performance? Is anything being copied? What does {args...} do in the first place? Is there a better method?
I have access to C++14.
Edit to be clear: It is about run time multiplication, not compile time.
More to be clear: I do not want to compute integers necessarily(although that is my current application), but the algorithm that I found was specialized for integers.
More: Arguments are of the same type. Algorithms without this restriction would be very interesting but maybe for a different question.
There are multiple questions asked here:
What's the impact on performance? Dunno. You'll need to measure. Depending on the type of the arguments I can imagine that the compiler entirely optimizes things either way, though: it does know the number of arguments and the types.
What is { args... }? Well, it creates an std::initializer_list<T> for the common type of the arguments (assuming there is one). You may want to use the value with std::common_type_t<T...> instead of a fixed type, though.
Is there a better method? There are a couple of approaches although I could imagine that the compiler actually does rather well with this expansion. The alternative which immediately comes to mind is return (args * ... * 1); which, however, requires C++17. If there is at least one argument the * 1 can be omitted: it is there to avoid a compile-time error if there is an empty list of variadic parameters.
The code
template<typename... T>
u64 Multiply(T... args)
{
u64 res = 1;
for (const u32& size : {args...})
res *= size;
return res;
}
is a bit mysterious to me :-) Why we have template parameters with type T and inside the method we used fix size values? And the variable name size looks very obscure because this var has nothing to do with any kind of size. And using integer types inside is also not a valid assumption if you give floating point data into the template.
OK, but to answer your question:
The first one can be used with all types you put into the template function. The second one used fixed ( unsigned integer ) types, which is not what I expect if I see the declaration of the template itself.
Both version can be made constexpr as I learned now :-) and work pretty well for compile time calculation.
To answer the question from your comment:
{args...}
expands to:
{ 1,2,3,4}
which is simply an "array" ( std::std::initializer_list) and only works if all elements have the same type.
So having
for (const u32& size : {args...})
simply iterates over the array.
Related
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.)
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";
}
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 ...
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
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.
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.
I want to optimize a little programm/library i'm writing and since 2 weeks i'm somewhat stuck and now wondering if what i had in mind is even possible like that.
(Please be gentle i don't have very much experience in meta-programming.)
My goal is of course to have certain computations be done by the compiler, so that the programmer - hopefully - only has to edit code at one point in the program and have the compiler "create" all the boilerplate. I do have a resonably good idea how to do what i want with macros, but it is wished that i do it with templates if possible.
My goal is:
Lets say i have a class that a using programmer can derive from. There he can have multiple incoming and outgoing datatypes that i want to register somehow so that the base class can do i'ts operations on them.
class my_own_multiply : function_base {
in<int> a;
in<float> b;
out<double> c;
// ["..."] // other content of the class that actually does something but is irrelevant
register_ins<a, b> ins_of_function; // example meta-function calls
register_outs<c> outs_of_function;
}
The meta-code i have up till now is this: (but it's not jet working/complete)
template <typename... Ts>
struct register_ins {
const std::array<std::unique_ptr<in_type_erasured>, sizeof...(Ts)> ins;
constexpr std::array<std::unique_ptr<in_type_erasured>, sizeof...(Ts)>
build_ins_array() {
std::array<std::unique_ptr<in_type_erasured>, sizeof...(Ts)> ins_build;
for (unsigned int i = 0; i < sizeof...(Ts); ++i) {
ins_build[i] = std::make_unique<in_type_erasured>();
}
return ins_build;
}
constexpr register_ins() : ins(build_ins_array()) {
}
template <typename T>
T getValueOf(unsigned int in_nr) {
return ins[in_nr]->getValue();
}
};
As you may see, i want to call my meta-template-code with a variable number of ins. (Variable in the sens that the programmer can put however many he likes in there, but they won't change at runtime so they can be "baked" in at compile time)
The meta-code is supposed to be creating an array, that is of the lengt of the number of ins and is initialized so that every field points to the original in in the my_own_multiply class. Basically giving him an indexable data structure that will always have the correct size. And that i could access from the function_base class to use all ins for certain functions wich are also iterable making things convinient for me.
Now i have looked into how one might do that, but i now am getting the feeling that i might not really be allowed to "create" this array at compile time in a fashion that allows me to still have the ins a and b be non static and non const so that i can mutate them. From my side they wouldn't have to be const anyway, but my compliler seems to not like them to be free. The only thing i need const is the array with the pointers. But using constexpr possibly "makes" me make them const?
Okay, i will clarify what i don't get:
When i'm trying to create an "instance" of my meta-stuff-structure then it fails because it expects all kinds of const, constexpr and so on. But i don't want them since i need to be able to mutate most of those variables. I only need this meta-stuff to create an array of the correct size already at compile time. But i don't want to sacrifice having to make everything static and const in order to achive this. So is this even possible under these kinds of terms?
I do not get all the things you have in mind (also regarding that std::unique_ptr in your example), but maybe this helps:
Starting from C++14 (or C++11, but that is strictly limited) you may write constexpr functions which can be evaluated at compile-time. As a precondition (in simple words), all arguments "passed by the caller" must be constexpr. If you want to enforce that the compiler replaces that "call" by the result of a compile-time computation, you must assign the result to a constexpr.
Writing usual functions (just with constexpr added) allows to write code which is simple to read. Moreover, you can use the same code for both: compile-time computations and run-time computations.
C++17 example (similar things are possible in C++14, although some stuff from std is just missing the constexpr qualifier):
http://coliru.stacked-crooked.com/a/154e2dfcc41fb6c7
#include <cassert>
#include <array>
template<class T, std::size_t N>
constexpr std::array<T, N> multiply(
const std::array<T, N>& a,
const std::array<T, N>& b
) {
// may be evaluated in `constexpr` or in non-`constexpr` context
// ... in simple man's words this means:
// inside this function, `a` and `b` are not `constexpr`
// but the return can be used as `constexpr` if all arguments are `constexpr` for the "caller"
std::array<T, N> ret{};
for(size_t n=0; n<N; ++n) ret[n] = a[n] * b[n];
return ret;
}
int main() {
{// compile-time evaluation is possible if the input data is `constexpr`
constexpr auto a = std::array{2, 4, 6};
constexpr auto b = std::array{1, 2, 3};
constexpr auto c = multiply(a, b);// assigning to a `constexpr` guarantees compile-time evaluation
static_assert(c[0] == 2);
static_assert(c[1] == 8);
static_assert(c[2] == 18);
}
{// for run-time data, the same function can be used
auto a = std::array{2, 4, 6};
auto b = std::array{1, 2, 3};
auto c = multiply(a, b);
assert(c[0] == 2);
assert(c[1] == 8);
assert(c[2] == 18);
}
return 0;
}
I'm trying to write a function for enumerating through a number of a specific base, where the number is stored in some kind of list. Here is an example, taking a std::vector
void next_value(std::vector<unsigned int> &num, unsigned int base) {
unsigned int carry = 1;
for (unsigned int &n: num) {
n += carry;
if (n >= base) {
carry = 1;
n = 0;
} else {
carry = 0;
}
}
}
The num vector doesn't necessarily need to be a vector, it can be an array, or actually any type that has a std::begin() and std::end() defined for it. Is there a way to express that num can be anything with begin() and end(), but that it must have unsigned int type for its elements?
If you really want to check this, try:
template <class Sequence>
void next_value(Sequence &num, unsigned int base) {
static_assert(boost::is_same<Sequence::value_type, unsigned>::value, "foo");
// ...
If you're not using C++11 yet, use BOOST_STATIC_ASSERT instead.
If you need to support plain C-style arrays, a bit more work is needed.
On the other hand, #IgorTandetnik correctly points out that you probably do not need to explicitly check at all. The compiler will give you an (ugly) error if you pass a type which is truly unusable.
Writing a generic function with a static_assert is a good idea, because you can give the user a helpful error message rather than "foo".
However there is another approach using C++11:
template <typename Container, typename ValueType>
typename std::enable_if<std::is_same<Container::value_type, ValueType>::value, void>::type
next_value(Container& num, ValueType base)
{
// ...
}
This is a rather cryptic approach if you've never seen this before. This uses "Substitution failure is not an error" (SFINAE for short). If the ValueType doesn't match the Container::value_type, this template does not form a valid function definition and is therefore ignored. The compiler behaves as if there is not such function. I.e., the user can't use the function with an invalid combination of Container and ValueType.
Note that I do recommend using the static_assert! If you put a reasonable error message there, the user will thank you a thousand times.
I would not in your case.
Change carry to a book, use ++ instead of +=, make base a type T, and n an auto&.
Finally, return carry.
Your code now ducktypes exactly the requirements.
If you want diagnostics, static assert that the operations make sense with custom error messages.
This let's your code handle unsigned ints, polynomials, bigints, whatever.
I wonder about the advantages of the new operator sizeof... (not to be confused with the sizeof operator). I searched the web and found a few examples that seem all like the following one:
template<class... ArgTypes>
std::size_t GetLength()
{
return sizeof...(ArgTypes);
}
I think the examples are not illustrative.
Are there any real examples to illustrate that sizeof... is very useful?
Updates:
I found another examples from here that seem more meaningful:
template<class ...A> void func(A ...args){
typedef typename common_type<A...>::type common;
std::array<common, sizeof...(A)> a = {{ args... }};
}
template<typename... A> int func(const A&... args)
{
boost::any arr[sizeof...(A)] = { args... };
return 0;
}
Here is my example of what you can do with sizeof...:
/// Transform a single boolean value into a number
constexpr unsigned int boolCode(bool value) {
return value;
}
/// Transform a sequence of booleans into a number
template <typename... Args>
constexpr unsigned int boolCode(bool value, Args... others) {
return value << sizeof...(others) | boolCode(others...);
}
And this handy function could be used in a switch statement, like this:
switch (boolCode(condition1, condition2, condition3)) {
case boolCode(false,false,false): //...
case boolCode(false,false,true): //...
case boolCode(false,true,false): //...
case boolCode(false,true,true): //...
case boolCode(true,false,false): //...
case boolCode(true,false,true): //...
case boolCode(true,true,false): //...
case boolCode(true,true,true): //...
}
you probably want to read discussion between STL and CornedBee in the comments:
http://channel9.msdn.com/Series/C9-Lectures-Stephan-T-Lavavej-Core-C-/Stephan-T-Lavavej-Core-Cpp-8-of-n#comments
Important bit:
sizeof... is not just syntactic sugar, though. A manually implemented
sizeof... would have linear "runtime" (number of instantiations),
whereas the built-in sizeof... is O(1). (One big issue of variadics as
they are is that compilation tends to be very slow, due to lack of
random access into arguments packs. Some guy (I think from Boost)
studied this and found that compilation speed of Boost.Tuple (a
preprorcessor-powered non-variadic tuple) compiled significantly
faster than a naive variadics-based version.)
The first and foremost reason sizeof was introduced into C++
was because it was present in C, where it is necessary in order
to know how much memory to allocate, e.g. malloc(
n * sizeof(struct MyClass) ). In C++, it's used in similar
cases, where allocation and initialization are separate, for
example in container classes, or variants, or maybe classes.
It's also been known to be used in template meta-programming, in
conjunction with function override resolution. Things along the
lines of: sizeof( discriminatorFunction( someArgs ) ) == sizeof(
TrueType ).
I need a bitset with a slightly diffrent behavior when asigning variables with integer type to a specific bit. The bit should be set to zero if the assigned integer is smaller then one, and to one elsewise.
As a simple solution I copied the STL bitset, replaced the classname with altbitset, adjusted namespaces and include guard and added following function under reference& operator=(bool __x) in the nested reference class:
template <typename T>
reference& operator=(T i) {
if (i<1) return operator=(false);
return operator=(true);
}
It works as expected.
Question is if there is a better way doing this.
You shouldn't copy a library just to add a new function. Not only that, the new function is wildly unintuitive and could possibly be the source of errors for even just reading the code, let alone writing it.
Before:
bv[n] = -1; // I know a Boolean conversion on -1 will take place
assert(bv[n]); // of course, since -1 as a Boolean is true
After:
bv[n] = -1; // I guess an integer < 1 means false?
assert(bv[n]); // Who changed my bitvector semantics?!
Just write it out so it makes sense in your domain:
bv[n] = (i < 1);
Remember: simplest doesn't always mean fewest characters, it means clearest to read.
If you do want to extend the functionality of existing types, you should do so with free functions:
template <typename BitSet, typename Integer>
auto assign_bit_integer(BitSet& bits, const std::size_t bit, const Integer integer) ->
typename std::enable_if<std::is_integral<Integer>::value,
typename BitSet::reference>::type
{
return bits[bit] = (integer < 1);
}
Giving:
std::bitset<8> bits;
assign_bit_integer(bits, 0, 5);
// ERROR: assign_bit_integer(bits, 0, 5.5);
But for such a small function with no clear "obvious" name that describes what it does concisely(assign_bit_true_if_less_than_one_otherwise_false is verbose, to say the least), just write out the code; it says the same thing anyway.