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.)
Related
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
Let's say I have a function
bool inline fn(int a) {
if (a == 0) {
a = 1; //or some other computation
return true;
}
return false;
}
int main() {
int a = 0;
if (fn(a)) {
return 1;
}
}
will the main code be roughly inlined to:
int a = 0;
bool test = false;
if (a == 0) {
a = 1; //or some other computation
test = true;
}
if (test) {
return 1;
}
thus resulting in two ifs, OR rather it would look more like this:
int a = 0;
if (a == 0) {
a = 1; //or some other computation
return 1;
}
which I obviously wanted to achieve. I'm using functions here not to make the executable smaller or anything, but purely to make the code more readable.
Actually why I do this is in the next example – imagine the function fn is templated, so that I can choose of more implementations of the function, while having the caller function exhibiting common behavior to all it's template instances, delegating the specific functionality to called functions.
Again this usage is purely for code reuse and readability. The functions will called/inlined in a single place in the code (that is the base_function).
I want to know, if tests on return values of the functions are efficiently optimized, so this code reuse technique doesn't interfere with performace/ actual execution at all.
template<typename TagSwitch, typename ... Args>
void base_function(Args ... args) {
// some base behavior meant to be common to all functions "derived" from this function
if (do_end(TagSwitch(), args ...)) {
return;
}
//specific_behavior(TagSwitch(), args ...);
}
// default for all specific ("derived") functions is don't end
template<typename TagSwitch, typename ... Args>
bool inline do_end(TagSwitch, Args ... args) {
return false;
}
// here I define my specific ("derived") function
struct MySpecificFunctionTag {};
template<typename ... Args>
bool inline do_end(MySpecificFunctionTag, int a, Args ... args) {
if (a == 0) {
//Do something (set a parameter)
return true;
}
return false;
}
int main() {
base_function<MySpecificFunctionTag>(1);
}
I'd like to know, if the test if (do_end(TagSwitch(), args ...)) { in base_function<MySpecificFunctionTag>(1) instantiation would result in two ifs or one would be optimized out.
Is testing for a return value of an inline (templated) function, which is itself testing, optimized to one test?
It can be optimized to one test, yes. In fact, both of your tests can be optimized away, since the value of the tested expression can be known at compile time. The entire program can be optimized to:
main:
mov eax, 1
ret
I.e. Always return 1, and do nothing else. The latter, template example returns 0 instead, but is otherwise identical.
The test cannot be optimized away from the function fn, and the check after the function call cannot be optimized away unless the return value of the function can be known at compile time. So, a prerequisite for merging the tests to one is that the optimizer must be able to expand the call inline.
I am working on a project where the behavior of a certain function need to switch between a few values:
class James{
public:
James(){
if(a==0){
//do this
}else{
// do that
}
}
};
currently, 'a' is read from a config file at runtime. However, in practice, 'a' can be determined at compile-time, rather than run time. I am thinking about have a trait class
struct TraitZero{
constexpr int a = 0;
};
struct TraitOne{
constexpr int a = 1;
};
and then turn James into a template class
template<typename Trait>
class James{
constexpr int a = Trait::a;
public:
James(){
if(a=0){
//do this
}else{
// do that
}
}
};
I don't know where I got it wrong, but this does not compile.
I am wondering if anyone here has ever countered problems like this. Can anyone share some insights?
As has already been mentioned by skypjack, only static data members can be constexpr, and you need to use == instead of = in the conditional.
That said, since you want to determine a at compile time, it may be beneficial to you to branch based on a at compile time, as well. To do this, you can use SFINAE or (as of C++17) constexpr if.
Assuming the following three traits...
struct TraitZero{
static constexpr int a = 0;
};
struct TraitOne{
static constexpr int a = 1;
};
template<size_t N>
struct TraitN {
static constexpr int a = N;
};
We can do this as...
SFINAE:
template<typename Trait>
class James {
// Unnecessary, we can access Trait::a directly.
//static constexpr int a = Trait::a;
public:
template<bool AZero = Trait::a == 0>
James(std::enable_if_t<AZero, unsigned> = 0) {
std::cout << "Trait::a is 0.\n";
}
template<bool AOne = Trait::a == 1>
James(std::enable_if_t<AOne, int> = 0) {
std::cout << "Trait::a is 1.\n";
}
template<bool ANeither = (Trait::a != 0) && (Trait::a != 1)>
James(std::enable_if_t<ANeither, long> = 0) {
std::cout << "Trait::a is neither 0 nor 1.\n";
}
};
What this does is conditionally select one of the versions of James() based on the value of Traits::a, using dummy parameters to enable overloading; this is simpler for functions other than constructors and destructors, as enable_if can be used on their return type.
Note the use of template parameters, instead of directly checking Trait::a in the enable_ifs themselves. As SFINAE can only be performed with types and expressions in the immediate context of the functions, these are used to "drag it in", so to speak; I like to perform the logic while doing so, as it minimises the intrusiveness of the enable_if.
constexpr if:
template<typename Trait>
class James {
// Unnecessary, we can access Trait::a directly.
//static constexpr int a = Trait::a;
public:
James() {
if constexpr (Trait::a == 0) {
std::cout << "Trait::a is 0.\n";
} else if constexpr (Trait::a == 1) {
std::cout << "Trait::a is 1.\n";
} else {
std::cout << "Trait::a is neither 0 nor 1.\n";
}
}
};
As can be seen here, constexpr if can be used to create cleaner, more natural code than SFINAE, with the advantage that it will still be evaluated at compile time instead of run time; unfortunately, it isn't yet supported by most compilers. [In this particular case, each version of James() will also be one machine instruction shorter (when compiled with GCC 7.0), due to not using a dummy parameter to differentiate between overloads.]
More specifically, with constexpr if, statement-false is discarded if the condition is true, and statement-true is discarded if it's false; in effect, this basically means that the compiler sees the entire constexpr if statement as the branch which would be executed. In this case, for example, the compiler will generate one of the following three functions, based on the value of Trait::a.
// If Trait::a == 0:
James() {
std::cout << "Trait::a is 0.\n";
}
// If Trait::a == 1:
James() {
std::cout << "Trait::a is 1.\n";
}
// If Trait::a == anything else:
James() {
std::cout << "Trait::a is neither 0 nor 1.\n";
}
In either case, with the following code...
int main() {
James<TraitZero> j0;
James<TraitOne> j1;
James<TraitN<2>> j2;
}
The following output is generated:
Trait::a is 0.
Trait::a is 1.
Trait::a is neither 0 nor 1.
Each type's constructor will be coded specifically to output the appropriate line, and none of the three constructors will actually contain any branching.
Note that I only marked member a as unnecessary out of personal preference; since I can access Trait::a directly, I prefer to do so, so I won't have to check what a is if I ever forgoet. Feel free to use it if you want to, or if it's needed elsewhere.
a data members must be declared as constexpr and static to be used the way you are trying to use them:
struct TraitZero{
static constexpr int a = 0;
};
struct TraitOne{
static constexpr int a = 1;
};
Put aside the fact that it's be ill-formed as it stands, you wouldn't be allowed to access it as Traits::a otherwise.
The same applies to the class James:
template<typename Trait>
class James{
static constexpr int a = Trait::a;
//...
};
Note also that probably the following isn't what you want:
if(a=0){
Even if you were allowed to modify a (and you are not for it's a static constexpr data member), in this case you would have assigned 0 to a and constantly got the else branch.
Most likely you were looking for something similar but slightly different:
if(a == 0){
Below is an example based on your code once fixed:
#include<iostream>
struct TraitZero{
static constexpr int a = 0;
};
struct TraitOne{
static constexpr int a = 1;
};
template<typename Trait>
class James{
static constexpr int a = Trait::a;
public:
James(){
if(a==0){
std::cout << "0" << std::endl;
}else{
std::cout << "1" << std::endl;
}
}
};
int main() {
James<TraitZero> j0;
James<TraitOne> j1;
}
Why not pass a #define at compile time using the -D option?
For example: Including a #define in all .c source files at compile time
I have a function that normally returns integers, but since the semantic of the value may differ i want to strong-type those, so i introduced two types, e.g. Money and Time, simplified as
struct Money {
uint32_t value;
}
the function will return either Money or Time depending on a bool param. let's say it looks like this:
template <typename T> T getValue(bool mode) {
Money money;
Time time;
...
if (mode == ModeMoney) {
money = something * 2;//get it from somewhere - irrelevant for the example
return money;
}
if (mode == ModeTime) {
time = something * 100;
return time;
}
}
now the compiler will complain for the differing return types, so i add specialized template functions to return the value itself:
template <> Money variableValue<Money>(something) { return something * 2 };
template <> Time variableValue<Time>(something) { return something * 100};
this allows to drop the bool param on invocation and the main function now will change to this:
template <typename T> T getValue(bool mode) {
....//calculation of *something* is the same, we only need different output from the function
return variableValue<T>(something);
}
is this a good approach?
Following Ami's comment, I recommend you make two functions and a helper:
Time getTime() { return calculateSomething() * 100; }
Money getMoney() { return calculateSomething() * 2; }
Keep separate use cases separate; the primary purpose of templates is to make interfaces simpler, not implementations. But if you turn something that looks like it should be two functions into one using templates, that doesn't make the interface simpler, because it's not intuitive. (Neither, as your question shows, does it actually make the implementation simpler.)
As an alternative solution, you can use a traits class to do that and to avoid duplicating the code.
It follows a minimal example:
template<typename>
struct traits;
template<>
struct traits<Money> {
using return_type = Money;
static constexpr std::size factor = 2;
};
template<>
struct traits<Time> {
using return_type = Time;
static constexpr std::size factor = 100;
};
template <typename T>
traits<T>::return_type getValue() {
traits<T>::return_type ret;
// ...
ret = something * traits<T>::factor;
return ret:
}
If it's a suitable solution mostly depends on the real code and the actual implementation of getValue.
Questions about design issues aside, you seem to want a tagged union or variant variant<Time, Money>. The next C++ standard will have a variant class in the standard library, but until this is available you can use Boost.Variant. With this, the code looks like
std::variant<Money, Time> getValue(bool mode) {
if (mode) {
return std::variant<Money, Time>( Money{23} );
}
else {
return std::variant<Money, Time>( Time{42} );
}
}
auto m = std::get<Money>( getValue(true) );
auto m2 = std::get<Money>( getValue(false) );
assert( m != nullptr && m2 == nullptr );
You can also implement your own variant for Money and Time only by using a union:
struct TimeOrMoney
{
enum class Type {isTime, isMoney};
Type type;
union
{
Time time;
Money money;
}
}
An alternative may be to return a std::pair< boost::optional<Money>, boost::optional<Time> > and then check which of the two is actually set. This uses the special optional state as a tag to signal which value has been set.
I need a way to check if a templated class's type is void.
Here is my attempt:
template <typename target_type, typename start_function_type, typename end_function_type> class C_rule {
public:
//...
void setIntoEffect(bool true_or_false) {
if (true_or_false == true) {
for (size_t i = 0; i < targets.size(); i++) {
if (typeid(start_function_type) != typeid(void)) {
start_function_type start_function_return_value = enforceOnTarget(targets.at(i));
}
else {
enforceOnTarget(targets.at(i));
}
}
}
else if ((true_or_false == false) && (is_in_effect == true)) {
for (size_t i = 0; i < targets.size(); i++) {
if (typeid(end_function_type) != typeid(void)) {
end_function_type end_function_return_value = removeFromTarget(targets.at(i));
}
else {
removeFromTarget(targets.at(i));
}
}
}
is_in_effect = true_or_false;
}
protected:
//...
private:
//...
};
However, this generates a compiler error complaining about the two variables "start_function_return_value" and "end_function_return_value" being declared void when created an object of C_rule with "start_function_type" and "end_function_type" being void. I'm trying to prevent creating a variable to store the return value from the 'start' and 'end' functions for the rule, if the return type of those functions is void (since void functions obviously do not return anything). And, as you can see, I'm trying to use the typeid operator for that purpose, but it doesn't appear to be working. Apparently, the if statement is still being entered when the start_function_type and end_function_type is void, and I don't know why. Maybe typeid doesn't work with void? I googled the question, but couldn't find an answer, so that's why I'm asking it here.
Thanks in advance.
In C++11, you could use the standard std::is_same<> type trait to verify if two types are the same:
#include <type_traits>
// ...
bool same = std::is_same<T1, T2>::value;
In your case, this could become:
bool same = std::is_same<start_function_type, void>::value;
However, this would not solve your problem, because an if statement is not a compile-time (static) if: both branches of the if statement still have to compile.
What you could do is to specialize your class template for the cases where start_function_type or end_function_type is void, or to factor out the part of the code which deals with them into a separate, specialized class template.