Fold expression vs compile recursion - c++

In c++17 we have fold expression which can greatly simplify code that could otherwise be implemented using compiler-recursion and SFINAE or overloading.
For example, in the following code
#include <iostream>
#include <utility>
template<typename ...Args>
void printer(Args&&... args) {
(std::cout << ... << args) << '\n';
}
void printer_cpp11() { }
template <typename First, typename ...Args>
void printer_cpp11(First&& first, Args&&... args)
{
std::cout << first;
printer_cpp11(std::forward<Args>(args)...);
}
int main()
{
printer(3, 4, "hello");
std::cout << std::endl;
printer_cpp11(3, 4, "hello");
return 0;
}
the c++17 function printer (taken from cpp reference) does exactly the same job as its c++11 version printer_cpp11.
At compile-time, several overloads of the function printer_cpp11 are generated, whereas a single function printer is needed using fold expression.
Is there an advantage in terms of performance in using fold expressions over the c++11-style? Or can one assume that the compiler inlines all the overloads of printer_cpp11, creating code with equivalent performance?

Both versions would lead to the same codegen due to inlining, so run-time performance is exactly the same: https://gcc.godbolt.org/z/VIHTvZ (code cleaned of streams clutter).
However, compilation times and memory usage are expected to be way better with fold expressions than with recursive instantiations, and because of that, fold expression are generally preferred. Not to mention they are also provide for cleaner and easier to reason about code.

Just to add to #SergeyA's answer you can alleviate the need for the recursion and the empty function in the c++11 version by doing something like...
template <typename ...Args>
void printer_cpp11_norecursion( Args&&... args)
{
using do_ = int[];
do_{0,
(std::cout << args,0)...
};
}
Which should generate the same results as both of the other versions (https://gcc.godbolt.org/z/hyAyiz) with possibly better compile times on c++11.

The compiler will create a new instance of printer for each call with different arguments and in the function will unfold the operator<< calls:
https://godbolt.org/z/Zz9Ik9
You can also see what happens here: https://cppinsights.io/
But ultimately - measuring will reveal if it leads to a performance gain.

Related

What is the difference between std::invocable and std::regular_invocable concepts?

What is the difference between std::invocable and std::regular_invocable? Based on the description from
https://en.cppreference.com/w/cpp/concepts/invocable I would expect that the std::regular_invocable concept doesn't allow to change the state of of the function object when it is called (or at least the result of the calling should always return the same result).
Why the code below compiles?
Compiled with a command: g++-10 -std=c++2a ./main.cc.
#include <iostream>
#include <concepts>
using namespace std;
template<std::regular_invocable F>
auto call_with_regular_invocable_constraint(F& f){
return f();
}
template<std::invocable F>
auto call_with_invocable_constraint(F& f){
return f();
}
class adds_one {
int state{0};
public:
int operator()() {
state++;
return state;
}
};
int main()
{
auto immutable_function_object([]() { return 1; });
adds_one mutable_function_object;
// I would expect only first three will be compiled and the last one will fail to compile because the procedure is
// not regular (that is does not result in equal outputs given equal inputs).
cout << call_with_invocable_constraint(immutable_function_object) << endl;
cout << call_with_invocable_constraint(mutable_function_object) << endl;
cout << call_with_regular_invocable_constraint(immutable_function_object) << endl;
cout << call_with_regular_invocable_constraint(mutable_function_object) << endl; // Compiles!
}
Output of the program:
1
1
1
2
From the reference:
Notes
The distinction between invocable and regular_invocable is purely semantic.
This means that there is no way for the compiler to enforce the distinction through the concepts system, since that can only check syntactic properties.
From the introduction to the concepts library:
In general, only the syntactic requirements can be checked by the compiler. If the validity or meaning of a program depends whether a sequenced of template arguments models a concept, and the concept is satisfied but not modeled, or if a semantic requirement is not met at the point of use, the program is ill-formed, no diagnostic required.
Hypothetically, we could write:
template< class F, class... Args >
concept regular_invocable = invocable<F, Args...> &&
requires(F&& f, Args&&... args) {
auto prev = f;
std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
assert(f == prev);
// TODO assert that `args` are unchanged
// TODO assert that invoking `f` a second time gives the same result
};
However, this would not actually test that the assertion holds, since a requires clause is not invoked at run time but only checked at compile time.
regular_invocable tells the user of the function that it will assume, that the result calling that regular_invocable function with the same value of the arguments will result in the same return value, and might cache that result due to that.
Caching the result could either be done by the function that expects regular_invocable or the compiler could use that information to optimize away multiple function calls to the regular_invocable function when the value of the arguments stay the same. So right now it can be seen as documentation and compiler hint.
Similar to const_cast it might not always be possible for the compiler to check if it is valid. Due to that and because there is currently not attribute/keyword in the standard to mark a function to always return the same value, there is right now no way to enforce at compile time that the function passed regular_invocable really matches that requirement.

Getting active value in std::visit without knowing which value is active

I want to get the active value in a std::variant without knowing which one is active. I thought i could write a template visitor and use std::visit but it doesn't work.
#include <variant>
#include <string>
#include <iostream>
struct Visit_configuration {
template<typename Data_type>
Data_type operator()(Data_type& t) const
{
return t;
}
};
int main()
{
std::variant<int, std::string> v;
v = "hello";
std::cout << std::visit(Visit_configuration(), v); // expect "hello"
std::cin.get();
}
MSVC doesn't compile and throws:
error C2338: visit() requires the result of all potential invocations
to have the same type and value category (N4741 23.7.7
[variant.visit]/2).
note: see reference to function template instantiation 'int
std::visit&,0>(_Callable
&&,std::variant &)' being compiled
So how to fix this?
edit: I want to use the obtained value maybe also for other so putting cout in the template isn't what im looking for.
Ask yourself the question:
What is the return type of std::visit if you don't know what part of the variant is active?
That is the question that the compiler must answer. And the answer can't be "it depends" - you (as in, the compiler) must decide on exactly one type at compile-time. The visit call cannot possibly return different types at runtime.
If you want to work with different types "at runtime", you must be in a function templated on the type you want to work with. In other words, there must be different functions (or function template instantiations) to handle the "write an int to cout" and "write a string to cout" cases. You cannot do this in the same (non-templated) function.
The straightforward solution here is thus to put the std::cout << into your templated visitor function - that's the point of visiting: Specifying what is supposed to happen in each case.
If you want to "use the obtained value maybe also for [some] other [purpose]", then that "other purpose" should also be part of the/a visitor. Only then can you have that "other purpose" handle the different cases at once (e.g. in a templated function). Otherwise you must decide at compile-time already which type shall be used - the compiler is not going to leave that choice open for later (run time).
Return type of visitor function should be identical.
Create printer visitor instead:
struct PrinterVisitor {
template<typename T>
void operator()(const T& t) const
{
std::cout << t;
}
};
int main()
{
std::variant<int, std::string> v;
v = "hello";
std::visit(PrinterVisitor{}, v); // expect "hello"
}
And in your case, you can even have lambda:
int main()
{
std::variant<int, std::string> v;
v = "hello";
std::visit([](const auto& t){std::cout << t;}, v); // expect "hello"
}

Indefinite amount of generic types in template?

I want to make a custom print function that takes any amount of arguments and prints them all on new lines.
In javascript, the document.write and console.log functions can do this because javascript stores all arguments in an array. To my knowledge, c++ doesn't do this and can't because of type restrictions.
So is there a proper way to do this in c++? Take any amount of arguments, regardless of type, and print them all?
Yes there is with the new C+11 standard. Please take a look at this article :
http://en.wikipedia.org/wiki/Variadic_template
There is a pretty nice example also you can use as a starter.
You can use a variadic function, similar to printf, but you will still need to know the types of the arguments and how many there are to be able to access them properly.
A better approach would probably be to do something similar to how the << operator was overloaded for ostream or use a chainable function. You will in the end still be limited to types (or supertypes with virtual functions) you know about.
From Bjarne himself:
http://www2.research.att.com/~bs/C++0xFAQ.html#variadic-templates
His code as of today:
void printf(const char* s)
{
while (s && *s) {
if (*s=='%' && *++s!='%') // make sure that there wasn't meant to be more arguments
// %% represents plain % in a format string
throw runtime_error("invalid format: missing arguments");
std::cout << *s++;
}
}
template<typename T, typename... Args> // note the "..."
void printf(const char* s, T value, Args... args) // note the "..."
{
while (s && *s) {
if (*s=='%' && *++s!='%') { // a format specifier (ignore which one it is)
std::cout << value; // use first non-format argument
return printf(++s, args...); // "peel off" first argument
}
std::cout << *s++;
}
throw std::runtime error("extra arguments provided to printf");
}

Duplicating C/C++ functions at compile time

If I have a function A(), I am interested in finding a convenient method to create a function B() that has the exact same functionality as A(), differing only in name. The new function would be for a one-time use. The intent is to differentiate between calls to the same function in a somewhat primitive sampling profiler, and the duplicated function would only be used in this context. That is, it would never touch production code and only be used for tinkering.
First guess would be a macro that declares a function named B and creates an inlined call to A() inside of it. The problem here is that I'm not aware of a method in GCC to force an arbitrary function call to inline; it seems all inlining options are for function declarations rather than calls.
There may be some esoteric way to do it with templates, or possibly by tricking the compiler into inlining. I'm not sure it's possible. Any thoughts? Unfortunately the new C++ standard is not available, if it would make a difference.
Using templates
template<int x>
void A()
{
// ..
}
int main()
{
A<0>();
A<1>();
return 0;
}
Update
The compiler can be too smart and create only one body for A<0> and A<1>. At least Visual C++ 2010 does it in Release mode. To prevent it, just use the template parameter inside the function template body in logs or asserts. For example,
#include <iostream>
template<int x>
void A()
{
::std::cout << x << std::endl;
// ..
}
int main()
{
A<0>();
A<1>();
auto v0 = A<0>;
auto v1 = A<1>;
::std::cout << v0 << std::endl;
::std::cout << v1 << std::endl;
::std::cout << (v0 == v1) << std::endl;
return 0;
}
This works using templates:
#include <iostream>
template<typename T>
void foo() {
static int x = 0;
std::cout << &x << std::endl;
}
int main(int argc, char **argv) {
foo<int>();
foo<float>();
return 0;
}
If you execute that, you'll see two different values printed, reflecting the compiler generated code for both calls, even though the template parameter is unused. nm on the object file confirms this.
If this is a one-time debug hack, then why not:
#define A_CONTENT \
... // whatever
void A()
{
A_CONTENT
}
void B()
{
A_CONTENT
}
...
A(); // Call to A
B(); // Call to B
Macros are generally grim, but we're not talking about production code here, so who cares?
Having been down this road myself, the short answer is that even if you get the compiler to emit two identical duplicates of a function, the optimizing linker will notice that they're identical and fold them back together into one implementation. (And if you've turned off optimization in the linker, then your profile isn't valid anwyay).
In the context of a sampling profiler, I've found the easier approach is to make two tiny wrappers for the function instead:
void Func() { .... }
_declspec(noinline)
void A_Func( return Func(); }
void B_Func( return Func(); }
void C_Func( return Func(); }
Then when your profiler samples the callstack, you'll be able to differentiate between the different callsites of this function in a very straightforward way..
You could always define a macro, for example in Chromium we do the following to reuse code:
#define CHROMEG_CALLBACK_1(CLASS, RETURN, METHOD, SENDER, ARG1) \
static RETURN METHOD ## Thunk(SENDER sender, ARG1 one, \
gpointer userdata) { \
return reinterpret_cast<CLASS*>(userdata)->METHOD(sender, one); \
} \
\
virtual RETURN METHOD(SENDER, ARG1);
And we call them like:
CHROMEGTK_CALLBACK_1(PageActionViewGtk, gboolean, OnExposeEvent, GdkEventExpose*);
CHROMEGTK_CALLBACK_1(PageActionViewGtk, gboolean, OnButtonPressed, GdkEventButton*);
You can do something similar to do what you wanted. The above example shows us using two different implementations but with one common code base. For GTK callbacks.
It's a little unclear what you're really trying to do, but a really ugly solution would be to declare the body of A as a macro and then you can "inline" this macro within whatever functions you like.
Also, macros are evil. Never use them unless you really have to.
Why do you care so much about inlining it? If you create a wrapper function, there is a pretty good chance the compiler will inline it anyway. At the very least, you're unlikely to get a function frame constructed.
C++11 also lets you do this:
void A() {
...
}
...
auto B = [] () -> void { A(); };
You can now use B syntactically as though it was a function wrapping A.

How to check that template's parameter type is integral?

In the description of some std template function I saw something like:
if the template parameter is of integral type, the behavior is such and such.
otherwise, it is such and such.
How can I do a similar test? Perhaps dynamic_cast?
Since the function I write is for my personal use I can rely on myself to supply only correct parameters, but why miss a chance to learn something? :)
In addition to the other answers, it should be noted that the test can be used at runtime but also at compile-time to select the correct implementation depending on wether the type is integral or not:
Runtime version:
// Include either <boost/type_traits/is_integral.hpp> (if using Boost)
// or <type_traits> (if using c++1x)
// In the following, is_integral shoudl be prefixed by either boost:: or std::
template <typename T>
void algorithm(const T & t)
{
// some code
if (is_integral<T>::value)
{
// operations to perform if T is an integral type
}
else
{
// operations to perform if T is not an integral type
}
// some other code
}
However, this solution can be improved when the implementation of the algorithm greatly depends on the test. In this case, we would have the test at the top of the function, then a big then block and a big else block. A common approach in this case is to overload the function and make the compiler select the correct implementation using SFINAE. An easy way to do this is to use boost::enable_if:
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_integral.hpp>
template <typename T>
typename boost::enable_if<boost::is_integral<T> >::type
algorithm(const T & t)
{
// implementation for integral types
}
template <typename T>
typename boost::disable_if<boost::is_integral<T> >::type
algorithm(const T & t)
{
// implementation for non integral types
}
When invoking the algorithm function, the compiler will "select" the correct implementation depending on wether the template parameter is integral or not.
One possibility:
#include <type_traits>
#include <iostream>
struct trivial
{
int val;
};
int main()
{
std::cout << "is_integral<trivial> == " << std::boolalpha
<< std::is_integral<trivial>::value << std::endl;
std::cout << "is_integral<int> == " << std::boolalpha
<< std::is_integral<int>::value << std::endl;
std::cout << "is_integral<float> == " << std::boolalpha
<< std::is_integral<float>::value << std::endl;
return (0);
}
So you then use std::is_integral<> to determine the action.
If you are unable to use C++11 features, std::numeric_limits<T>::is_integer does the same thing as std::is_integral<T>::value, and is available with C++98.
Note that the 98 version is integer, not integral.
Boost.TypeTraits provides is_integral<>(), as described in another response, if your compiler does not yet support C++ features of the next standard.