If I have some code like this:
void function_1(...)
{
//do something
}
void function_2(...)
{
//do something
}
int function_3(...)
{
//do something
}
int main()
{
....
if (CONSTANT_1) function_1()
else if (CONSTANT_2) function_2()
else if (CONSTANT_3) function_3()
....
}
I would like avoid the if-else statement and do something like this in main function:
int main()
{
function<CONSTANT>();
}
How can I avoid the use of if-else statement and simulate this behavior?
In general you can specialize the function template:
template<int N>
void function();
template<>
void function<1>()
{
//do something
}
template<>
void function<2>()
{
//do something
}
template<>
void function<3>()
{
//do something
}
This works, but there might be better solutions as well.
Overload and tag dispatch. The Base template will convert the constant into a unique type. Then simple overload resolution will choose the proper overload. This is all assuming the constant are constexpr, and not something known only at run-time.
void function(std::integral_constant<int, CONSTANT_1>)
{
//do something
}
void function(std::integral_constant<int, CONSTANT_2>)
{
//do something
}
int function(std::integral_constant<int, CONSTANT_3>)
{
//do something
}
template<int constant>
auto function()
{
return function(std::integral_constant<int, constant>{});
}
int main()
{
function<CONSTANT_2>(); // calls the second overload
}
The above has the benefit of issuing a compile time error when an overload isn't found, as opposed to a linkage error if you specialize template functions instead.
Related
I'm new to c++, and coming from c#;
in c# to achieve my intended goal I would simply do this
public void MyMethod(int? value) {
if(value is null) {
// Do something
} else {
// Do something else
}
}
how might I achieve this result, if possible in c++?
You can do this with std::optional.
void MyMethod(const std::optional<int>& option) {
if(option.has_value()) {
// Do something with the int option.value()
} else {
// Do something else with no value.
}
}
std::nullopt is what you pass when no value is desired. MyMethod(std::nullopt);
Or if you want to be able to omit the argument entirely and say MyMethod() then you can make the argument default to std::nullopt.
void MyMethod(const std::optional<int>& option = std::nullopt) {
This sounds like a job for overloading:
void f() {
// do something for no argument
}
void f(int i) {
// do something with I
}
Can I call functions in function parameters?
void Function_1() {
//some code
}
void Function_2(void* Using_Function()) {
//some code
Using_Function();
//some code
}
int main() {
Function_2(Function_1);
return 0;
}
Is it even possible to do so?
I think you are asking about function pointers, if so then like this.
void Function_1() {
//some code
}
void Function_2(void (*Using_Function)()) {
//some code
Using_Function();
//some code
}
...
Function_2(Function_1);
My goal is to speed up my code by removing the runtime decision making of if-statements. Here's a simple example:
enum E
{
E_A,
E_B
};
class Example:
{
public:
void DoSomething(E var)
{
if (var == E_A) {
// Do stuff with a
} else if (var == E_B) {
// Do stuff with b
}
}
private:
set<int> a;
set<int> b;
}
I've split the above DoSomething() function into 2.
void DoSomething(E::E_A var) {
// Do stuff with a
}
void DoSomething(E::E_B var) {
// Do stuff with b
}
The problem is I have to rewrite the same code twice... We could use an inbetween function:
void DoSomething(E_A var) {
InBetween(a);
}
void DoSomething(E_B var) {
InBetween(b);
}
void InBetween(set<int> s)
{
// Do something with s
}
set<int> a;
set<int> b;
However I was wondering if there's a way to achieve what I want with just a single DoSomething()? I want the code to have minimal runtime so please avoid solutions like storing storing a and b inside a map and looking up based on key.
Or please suggest me some areas to look into. Thanks in advance!
You can make DoSomething template (and var template parameter). Then you can apply Constexpr If (since C++17), which performs dispatch at compile-time. E.g.
template <E var>
void DoSomething()
{
if constexpr (var == E_A) {
// Do stuff with a
} else if constexpr (var == E_B) {
// Do stuff with b
}
}
Then call it as
a_Example.DoSomething<E::E_A>();
a_Example.DoSomething<E::E_B>();
I would like to create something similar to rust unsafe scope in C++.
The idea is that I have some functions performing number of checks. For example:
void check() {
if (...)
throw exception(...);
}
void foo() {
check();
// do some work
}
Now, I want to be able to call function foo() with or (in different context) without performing those checks. Ideally it would look like this:
foo(); // call foo and perform checks
unsafe {
foo(); // call foo without checks
}
My question is, is it possible to achieve something like this in compile time? Is it possible to somehow check (or act differently) from check function in what scope it is called?
I came up only with a runtime solution: to wrap it in some lambda:
unsafe([&] {
foo();
});
where unsafe is implemented as follows:
void unsafe(std::function<void()> f)
{
thread_local_flag = unsafe;
f();
thread_local_flag = safe;
}
check() function would just check for the thread_local flag and perform checks only when it is set to safe.
🤔
namespace detail_unsafe {
thread_local int current_depth;
struct unsafe_guard {
unsafe_guard() { ++current_depth; }
~unsafe_guard() { --current_depth; }
unsafe_guard(unsafe_guard const &) = delete;
unsafe_guard &operator = (unsafe_guard const &) = delete;
};
}
#define unsafe \
if(::detail_unsafe::unsafe_guard _ug; false) {} else
bool currently_unsafe() {
return detail_unsafe::current_depth > 0;
}
See it live on Coliru. Also, please don't actually define unsafe as a macro...
is it possible to achieve something like this in compile time?
Not the way you presented. Making foo a template function might give you equivalent results, though:
enum class CallType // find a better name yourself...
{
SAFE,
UNSAFE,
};
template <CallType Type = CallType::SAFE>
void foo()
{
if constexpr(Type != CallType::UNSAFE)
{
if (...)
throw ...;
}
// do some work
}
You might call it like:
foo();
foo<CallType::UNSAFE>();
Disliking templates?
Simple approach (thanks, #VTT):
void check(); // no template any more
void foo_unsafe()
{
// do some work
}
inline void foo()
{
check();
foo_unsafe();
}
Or selecting via parameter (this pattern exists in standard library, too):
struct Unsafe
{
};
inline Unsafe unsafe;
void check();
void foo(Unsafe)
{
// do some work
}
inline void foo()
{
check();
foo(unsafe);
}
Edit:
Well, in the example I presented I could do that, but in general, I can call some other function bar inside unsafe which in turn calls foo. And I don't want to specialize bar and possible other methods.
Unter this constraint, the template variant might be the closest you can get to at compile time; you don't have to specialise all the functions, but you'd need to make templates from:
template <CallType Type = CallType::SAFE>
void bar()
{
// do some other work
foo<Type>(); // just call with template parameter
// yet some further work
}
I would simply use a RAII type to toggle the unsafe flag inside a scope as such:
thread_local bool unsafe_flag = false;
/// RAII Type that toggles the flag on while it's alive
/// Possibly add a reference counter so it can be used nested
struct unsafe_scope
{
constexpr unsafe_scope() { unsafe_flag = true; }
~unsafe_scope() { unsafe_flag = false; }
};
/// Gets a value from a pointer
int get_value(int* ptr)
{
if ( unsafe_flag )
{
if ( ptr == nullptr ) { return 0; }
}
return *ptr;
}
int main()
{
int* x = nullptr;
//return get_value(x); // Doesn't perform the check
{
unsafe_scope cur_scope;
return get_value(x); // Performs the check
}
}
In order to make it nested I would add a reference counter like this:
/// RAII Type that toggles the flag on while it's alive
struct unsafe_scope
{
thread_local static size_t ref_count;
constexpr unsafe_scope()
{
unsafe_flag = true;
ref_count++;
}
~unsafe_scope()
{
ref_count--;
if ( ref_count == 0 ) { unsafe_flag = false; }
}
};
/// In source file
thread_local size_t unsafe_scope::ref_count = 0;
The ref_count doesn't need to be atomic since it's thread_local
Now I don't think there's a way to achieve the syntax you wanted with the unsafe before the scope, but if you put it right after the scope as such it should be about the same:
{ unsafe_scope cur_scope;
return get_value(x); // Performs the check
}
Edit:
I've now noticed Quentin's answer is also a RAII type, just with slightly different semantics, instead of having a global thread_local flag a function just returns if the reference counter is bigger than 0. Also the macro achieves the exact syntax you wanted, although it's also possible with this unsafe_scope by modifying his macro like this:
#define unsafe\
if (unsafe_scope cur_scope; false) {} else
His method uses C++17's if initializer, which lets you initiates a variable in the if statement, but the variable is still initialized in the else block, so it only gets destroyed after the else scope if over.
lets say for example i have the following code:
bool foo1() {
check something...
}
void foo2() {
do something ...
}
void foo3() {
do something ...
}
void foo4() {
do something ...
}
void foo5() {
do something ...
}
void foo6() {
if (foo1()) foo2();
if (foo1()) foo3();
if (foo1()) foo4();
if (foo1()) foo5();
}
is there a better way to do this? i don't want to write the if statement every time, but each of the other functions might change the calculation of foo1().
i have a series of different functions and i want it to use foo1() before every call.
You could put the functions in a container and then use a loop:
std::vector<void (*)()> functions = {foo2, foo3, foo4, foo5};
for (auto f: functions)
if (foo1())
f();