What I am looking for is the log function that will log message, but only once per call site.
It would be useful to log first occurrence of an error, timeout, etc, without spamming the cout/log files.
Traditionally it has been implemented with macros(where they expand to some static bool/counter, you can see LOG_FIRST_N in glog for details), but I wonder if in C++20 it can be done without macros.
What I have tried:
Use std::source_location as template param, based on this answer, does not work since magic of std::source_location::current() does not work as I want it to work.
note: I know I can have one static std::set/std::unordered_set of call sites, but I am interested in solutions that is as efficient as the evil MACRO solution.
As every lambda expression is of different type, you can use lambda expressions to tag calls to the same function.
For example this:
#include <iostream>
template <typename T,typename F>
void once(T t, F f){
static bool first = true;
if (first) {
f();
first = false;
}
}
int main(){
for (int i=0; i <1000; ++i){
once([](){},[](){ std::cout << "A";});
}
for (int i=0; i <1000; ++i){
once([](){},[](){ std::cout << "B";});
}
}
Prints
AB
However, once([](){},... is a bit unwieldy and it is still tempting to use a macro.
PS: As mentioned in a comment, since C++20 the lambda can be used as default argument for the template and even before you can do:
#include <iostream>
template <typename F,typename T>
void once_impl(F f, T t){
static bool first = true;
if (first) {
f();
first = false;
}
}
template <typename F>
void once(F f) { once_impl(f,[](){});}
int main(){
for (int i=0; i <1000; ++i){
once([](){ std::cout << "A";});
}
for (int i=0; i <1000; ++i){
once([](){ std::cout << "B";});
}
}
if(error)
static const bool error_logged=error_log << "message\n";
the first time error is true, the stream will be written to. Every other time, nothing. It is thread safe; if 2 threads both have the error, it is guaranteed exactly one runs the log code.
error_logged will store true if the write worked, false otherwise.
C++ does not have a way to inject state to the calling location from within a function call (barring coroutines, which are not zero cost). So the state -- "have I called this before, here" -- must be at the calling site.
The amount of state required is minimal; as you can see above, a branch plus a static local is enough.
The evil macros are usually more complex because they want to be usable in more complicated structures, like:
return a?b:(log("error!"), c);
You might wrap the logic in template, and in C++20, lambda can be used as default template argument:
So you might do
template <typename F, typename Tag = decltype([](){})>
// or template <typename F, auto Tag = [](){}>
void simple_do_once(F f /*, Tag={}*/ )
{
static std::once_flag flag;
std::call_once(flag, f);
}
Demo
Related
I would like to generate a function that forwards its arguments to another function. I know that std::function does it somehow, but I cannot seem to find the right syntax myself.
It would be ok for my usecase to use som kind of template magic, but i want
the user to be able to get information on the calling types when they use the function, like std::function does.
My usecase uses class member functions, so a solution that only works in that context is accepted. I tried to created the smallest example code possible.
#include <iostream>
// Macro usage cannot be changed
#define ARGS int, int
void otherFunction(int x, int y) {
std::cout << x << "," << y << "\n";
}
// This is the behaviour i want
void expectedImplementation(int _1, int _2) {
otherFunction(_1, _2);
}
// This works, but it prevents the user to view the expected
// types in their IDE
template <typename ...Args>
void templateVersion(Args ... args) {
otherFunction(args...);
}
// This is the version I cannot get to work
// It does not need to look like this, but it needs to get
// its argument types from
//void func(ARGS) {
// otherFunction(/*how?*/);
//}
int main() {
expectedImplementation(1, 2);
templateVersion(1, 2);
//func(1, 2);
}
godbolt
How do I accomplish this?
Edit:
The function that needs to be forwarded to is also different for each instance of the function.
Edit 2:
Ok, It seems like it's hard to specify the context without the context. Here is the actual code that I want to generalize. Here Is the template magick stuff where it should fit in. No memory should be used, otherwise I would just use the solution I have now with template parameter packs.
Edit 3:
A better example:
#include <iostream>
#define ARGS int, int
struct Inner {
void otherFunction(int x, int y) {
std::cout << x << y << std::endl;
}
};
struct Wrapper {
Inner inner;
// This works, but it prevents the user to view the expected
// types in their ide
template <typename ...Args>
void templateVersion(Args ... args) {
inner.otherFunction(args...);
}
// The concept I try to figure out
void function(ARGS) { // It does not need to look exactly like this
// , but functionally it needs to be somithing like it
// Forward the arguments to the `ìnner` class
}
};
int main() {
auto wrapper = Wrapper{};
wrapper.templateVersion(10, 20);
}
Your macro ARGS does not define named arguments. You cannot forward the type of unnamed arguments. That's a limitation of the language.
Either forget about using macros, and change your function definiton:
void func(int a, int b) {
otherFunction(a, b);
}
Or change the definition of the macro:
#define ARGS int a, int b
void func(ARGS) {
otherFunction(a, b);
}
That said, nothing beats the template solution. Make sure you use perfect forwarding.
template <typename ...Args>
void templateVersion(Args&& ... args) {
otherFunction(std::forward<Args>(args)...);
}
I have class that is managing a number of similar member variables of different, but similar type.
class Manager {
Type1 a;
Type2 b;
Type3 c;
void process();
};
Although the types are different, they share some functions and attributes. At least this lets me use some templated functions to process the class members in a similar way.
template <typename T>
void process(T& t) {
// do something with t
}
void Manager::process() {
process(a);
process(b);
process(c);
}
At one point in my program I also need to supply strings equal to the member variable names.
template <typename T>
void print(T t, std::string name) {
std::cout << name << ": " << t.msg << std::endl;
}
void Manager::print() {
print(a, "a");
print(b, "b");
print(c, "c");
}
I have reduced the code samples to illustrate my problem. In reality, there are many more places where I simply copy-paste entire blocks of code for each variable. Every now and then, a new member variable with a new type is added.
What pattern can I use to avoid these seemingly unnecessary repetitions of similar code?
I have thought of something like a std::map<std::string, ParentType> members;. I guess this would allow me to loop over all member variables instead of copy-pasting code and I could also store a corresponding name string for each variable. However, the types that I use have no common parent class and are third-party, i.e. I cannot modify the implementation of Type1/Type2/Type3/...
I guess what I really want is to have only a single place where I define types and names and then being able to simply loop over all variables for performing similar processing.
I can think of partially solving this using preprocessor macros, but aren't those rather discouraged in modern code?
It seems like this is exactly the use case for the preprocessor---removing repeating code and stringifying identifiers. If you don't like it, and you don't mind the horrible syntax, you could make Manager a tuple:
class Manager {
std::tuple<Type1, Type2, Type3 /* more types can be added ... */> tup;
}
Then you can run a function on each element using std::apply. See Template tuple - calling a function on each element.
void Manager::process() {
std::apply([](auto ...x){
std::make_tuple(process(x)...);
}, this->tup);
}
Without reflection I believe there is no cleaner solution. And your stringify print example is impossible without macros.
You might create template function for your class, something like:
class Manager {
Type1 a;
Type2 b;
Type3 c;
template <typename F>
void apply(F f)
{
f(a); f(b); f(c);
}
template <typename F>
void apply_with_name(F f)
{
f("a", a); f("b", b); f("c", c);
}
void process() { apply([](auto& t){ t.process(); }); }
void print() { apply_with_name([](const std::string& name, auto& t){ std::cout << name << ": " << t.msg << std::endl; }); }
};
I have a lengthy unit test code snippet that I want to run for two functions. I am wondering if there's a way to do this without copy and paste the code and only change the function name?
Say the test code looks like
int main(){
output1 = function(input1);
assert output1 == answer1;
output2 = function(input2);
assert output2 == answer2;
output3 = function(input3);
assert output3 == answer3;
......
outputN = function(inputN);
assert outputN == answerN;
}
Now say I have two function func1 and func2. I want to ran literally the same test for func1 and func2. I am wondering if there's a neat way to do this in C++ without involving some test framework? Thanks in advance for any help.
You can make a function template:
template <typename F, typename R, typename Args...>
void test_func(F f, R&& r, Args&&... args) {
auto output = f(std::forward<Args>(args)...);
assert(output == std::forward<R>(r));
}
then use it like
test_func(&func1, answer1, input1);
test_func(&func2, answer2, input2);
...
Additional explanations:
The parameters and return value are passed by forwarding reference, then their value categories will be reserved when being passed to the function (with the usage of std::forward).
The parameters is declared as parameter pack then you can pass multiple ones with any types.
C++ supports passing parameters to functions ;).
You can pass functions to functions. To keep it simple, I am assuming that all functions you want to test have the same signature. To avoid verbose syntax of function pointers I'd use a template:
template <typename F>
void test_function(F f, std::vector<input_type> input,std::vector<output_type> expected) {
for (size_t i = 0; i < input.size(); ++i) {
assert( f(input[i]) == expected[i]);
}
}
int main() {
test_function( func1, {1,2,3},{2,3,4} );
test_function( func2, {1,2,3},{6,7,8} );
}
PS: From my own experience I can tell you that it isn't worth to put much work into hand-written test facilities. You will find yourself wanting more and more features that a test framework offers out of the box (eg logging test reports). Googletest is something I can recommend.
A solution of C methed is to use fuction pointer. But I recommand lambda fuction pulished in c++11. u can use as follow:
template<typename Func>
void test(intput in, output out, Func func) {
answer = func(in);
assert(out == answer);
}
void main() {
intput intput1;
output output1;
test(input1, output1, [&](intput in)->output{return func1(in)});
test(input1, output1, [&](intput in)->output{return func2(in)});
}
After all, u should add compile para:-std=c++11 while using g++ compiler.
Here's my new take, this should compile. It's built in layers so you can see how to expand each layer as you see fit. It doesn't work exactly as your example does, there are copies being made of your input data and there is no assignment operation for the output. You should take these into account and adjust accordingly (if required).
// Example program
#include <functional>
#include <assert.h>
#include <vector>
#include <utility>
// function to test
int func1(int p_param)
{
return p_param;
}
// function to test
int func2(int p_param)
{
return p_param;
}
// Test runner base
template <typename TFunction, typename TInput, typename TOutput>
void test_runner(TFunction f, std::vector < std::pair<TInput, TOutput> > p_testparameters)
{
for (auto pair : p_testparameters)
{
assert(f(pair.first) == pair.second);
}
}
// Specific test 1
template <typename TFunction>
void test1(TFunction f)
{
test_runner<TFunction, int, int>(f, { {1,1},{2,2},{3,3} });
}
// Specific test 2
template <typename TFunction>
void test2(TFunction f)
{
test_runner<TFunction, int, int>(f, { {10,10},{20,20},{30,30} });
}
// Run tests for function
template <typename TFunction>
void runTests(TFunction f)
{
test1(f);
test2(f);
}
int main() {
runTests(func1);
runTests(func2);
return 0;
}
Basically, I want to find a template in a parameter pack that satisfies some runtime conditions. Intuitively, I just want to iterate over my instantiations of the parameter pack and find the first which satisfies a condition. My current simplified toy implementation to demonstrate what I mean:
Find the struct of X and Y which satisfies their test() first.
struct X {
bool test(int i) {
flag = i > 10;
return flag;
}
bool flag;
std::string value = "X satisfied first";
};
struct Y {
bool test(int i) {
flag = i > 11;
return flag;
}
bool flag;
std::string value = "Y satiesfied first";
};
This struct finds the first struct of X and Y to satisfy the condition. In this example it increases an integer up to a given limit until one of the structs reports that its test() was successful.
template <typename... Ts> struct FindFirst {
static std::string find_first(int limit) {
return find_first_satisfying(limit, Ts{}...);
}
static std::string find_first_satisfying(int limit, Ts... ts) {
int i = 0;
bool satisfied = false;
while (i < limit && !satisfied) {
satisfied = (ts.test(i) || ...);
i++;
}
return extract(ts...);
}
template <typename T, typename... OtherTs>
static std::string extract(T t, OtherTs... ts) {
if (t.flag) {
return t.value;
} else {
if constexpr (sizeof...(OtherTs) > 0) {
return extract(ts...);
} else {
return "Nobody satiesfied condition";
}
}
}
};
This implementation generates as many different extract() functions with different signatures as there are templates in the pack. They get "recursively" called and result in a deep call stack (depends on the position of the satisfying struct) and large bytecode.
Is there a method to construct a loop (at compile-time) which tests each instantiation of the parameter pack and stops appropriately?
Also, any other suggestions on how to simplify the whole construct?
I would wrote your code something like that:
template <typename ... Ts>
std::string find_first_satisfying(int limit, Ts... ts)
{
for (int i = 0; i != limit; ++i) {
std::string res;
bool found = false;
([&](){ if (ts.test(i)) { found = true; res = ts.value; } return found;}() || ...);
if (found) { return res; }
}
return "Nobody satisfied condition";
}
Demo
No. It is possible that in C++23 it won't be like this but currently there is no guarantee.
But is there problem really? The only issue I see is that the code is hard to write and understand. Large bytecode is of little significance and optimizer should be able to inline and optimize everything - only debug performance should suffer as a result (and compile time)... Unless you write the program in a manner that makes optimizer/compiler unable to inline it (by hiding bodies of functions).
P.S. can't you somehow write extract as an operator and use the ... instead of recursion? Though, I think it is a bad idea for various reasons. (I see that #Jarod42 wrote it via lambda in another answer, it looks good to me.)
Say I have a function that takes a variable number of parameters: I want to call this function from somewhere else, building the list of parameters, but without knowing in advance how many parameters I'll need.
Sorry that's not well explained, hopefully this code makes my question clearer:
void foo(int n, ...) {
va_list vl;
va_start(vl,n);
for (int i = 0; i<n; i++) {
// Do something to each passed variable
}
}
That function's being called from this one:
void bar(int howManyParams) {
// Here I want to call foo() with howManyParams parameters
// (values are irrelevant for the question)
//
// I.e. for howManyParams = 1, we should call foo(0)
// for howManyParams = 2, we should call foo(0,0)
// for howManyParams = 3, we should call foo(0,0,0)
// etc.
//
}
Actually building a variable-length argument list at run-time -- which is what I'm pretty sure you're trying to do -- is pretty tricky. There's no way to do it at all in Standard C, but there are various tricks you can try.
Perhaps the best is the "Foreign Function Interface Library" at http://sourceware.org/libffi/ .
See also question 15.13 in the C FAQ list: http://c-faq.com/varargs/invvarargs.html
See also these previous Stackoverflow questions:
C late binding with unknown arguments
How to call functions by their pointers passing multiple arguments in C?
You will need a terminating parameter, it may be NULL, or something else, that should never appear in your real arguments. Inside your function you can loop over the arguments until you reach a terminating NULL or any other value you choose to signal the end.
If a special value cannot be reserved to indicate the end of the list, pass 2 arguments for each parameter. Tad wasteful but does allow code to be sequentially automatically generated without value restrictions.
foo(0);
foo(1, Params1, 0);
foo(1, Params1, 1, Params2, 0);
foo(1, Params1, 1, Params2, 1, Params3, 0);
The easier way to do at runtime what the OP asked is probably by relying on standard containers like std::vectors and the others.
Anyway, for the sake of completeness, here is an example of how a variadic pack of parameters can be created at compile time and used later to invoke a function:
#include<utility>
#include<tuple>
#include<iostream>
auto params(std::index_sequence<0>) {
return std::tuple<std::size_t>{};
}
template<std::size_t I, std::size_t... O>
auto params(std::index_sequence<I, O...>) {
auto tup = std::tuple<std::size_t>{ sizeof...(O) };
auto seq = std::make_index_sequence<sizeof...(O)>{};
return std::tuple_cat(tup, params(seq));
}
void foo() {
std::cout << "done." << std::endl;
}
template<typename Arg, typename... Args>
void foo(Arg &&arg, Args&&... args) {
std::cout << "arg: " << arg << ", still to be elaborated: " << sizeof...(Args) << std::endl;
foo(std::forward<Args>(args)...);
}
template<typename... Args, std::size_t... Indexes>
void invoke(std::tuple<Args...> &tup, std::index_sequence<Indexes...>) {
foo(std::get<Indexes>(tup)...);
}
template<std::size_t N>
void bar(std::integral_constant<std::size_t, N> size) {
auto seq = std::make_index_sequence<N>{};
auto tup = params(seq);
invoke(tup, seq);
}
int main() {
bar(std::integral_constant<std::size_t, 3>{});
bar(std::integral_constant<std::size_t, 5>{});
}
Unfortunately, for it must be completely resolved at compile time, the argument for the bar function cannot be a std::size_t for itself.
Instead, a std::integral_constant can be used to do that.
When I've need to do something like this, I got it to work with a "switch-fan".
switch( n ){
case 1: foo(0); break;
case 2: foo(0,0); break;
case 3: foo(0,0,0); break;
}