I have this code
class Foo {
private:
enum class Heuristic {
ONE,
TWO,
THREE
};
Heuristic h;
void select();
};
void Foo::select() {
if (h == Heuristic::ONE)
selectONE();
else if (h == Heuristic::TWO)
selectTWO();
else
selectTHREE();
}
void selectONE() {};
void selectTWO() {};
void selectTHREE() {};
Based on the value of heuristic I want to call a specific function in select(). I don't know the value of heuristic at compile time, as it depends on user input. To avoid the conditional check in select() I would like to use templates. How can I accomplish this?
As it depends on runtime values there is no way to get rid of some sort of runtime checks. Which are either done by you with if, switch, … or by a container like std::map, std::unordered_map
Due to that, your concern there should be readability and maintainability.
I would - like already suggested in a comment - use switch instead of if, but not because the compiler can optimize it better (IMHO the compiler will be able to generate the same code for both), but to allow the static analyzer to warn you about not used enums.
If the question is about performance concerns, then this should only be a problem if you call these functions at a high frequency. So if this is the case you could create a template-based entry point to your task, to which you pass the function as template argument based on the user selection:
template<auto SelectedHeuristic>
void Foo::task() {
for( /* … */ ) {
SelectedHeuristic();
}
}
void Foo::select() {
switch(h) {
case Heuristic::ONE:
Foo::task<selectONE>();
break;
case Heuristic::TWO:
Foo::task<selectTWO>();
break;
case Heuristic::THREE:
Foo::task<selectTHREE>();
break;
}
}
void selectONE() {};
void selectTWO() {};
void selectTHREE() {};
To avoid the conditional check in select() [...]
A simple way to avoid all conditional checks (hidden or otherwise) in select() could be to create an array of pointers to your functions. You then look the function up by using its current Heuristic value (which must start at 0 and not have any gaps). If the Heuristic value changes rarely, you can even move the lookup out of select() completely.
Example:
##include <iostream>
void selectONE() { std::cout << "one\n"; };
void selectTWO() { std::cout << "two\n"; };
void selectTHREE() { std::cout << "three\n"; };
using func_ptr_t = void(*)(); // the signature of your functions
class Foo {
public:
enum class Heuristic {
ONE,
TWO,
THREE
};
void set_heuristic(Heuristic); // a function to do the lookup
void select();
private:
Heuristic h;
func_ptr_t current_func; // a pointer to the selected function
};
void Foo::set_heuristic(Heuristic value) {
// a simple map from Heuristic value to function pointer
static const func_ptr_t funcmap[] = {
&selectONE,
&selectTWO,
&selectTHREE,
};
h = value; // perhaps not needed?
// look up the function pointer based on "h"
current_func = funcmap[static_cast<unsigned>(h)];
}
void Foo::select() {
// a pretty fast callsite:
current_func();
}
int main() {
Foo bar;
bar.set_heuristic(Foo::Heuristic::ONE);
bar.select(); // prints "one"
}
define a map<Heuristic, lambdas> where the lambdas are defined as
void and taking no parameters
void f()
then take the user input and get the value of that input key and trigger the lambda
Related
Lets say I'm trying to write multiple handlers for multiple message types.
enum MESSAGE_TYPE { TYPE_ZERO, TYPE_ONE, TYPE_TWO, TYPE_THREE, TYPE_FOUR };
One solution might be
void handler_for_type_one(...){ ... }
void handler_for_type_two(...){ ... }
...
switch(message_type){
case TYPE_ONE: handler_for_type_one(); break;
case TYPE_TWO: handler_for_type_two(); break;
...
And yeah, that would work fine. But now I want to add logging that wraps each of the handlers. Let's say a simple printf at the beginning / end of the handler function (before and after is fine too).
So maybe I do this:
template<MESSAGE_TYPE>
void handler() {
std::printf("[default]");
}
template<> void handler<TYPE_ONE>() {
std::printf("[one]");
}
template<> void handler<TYPE_TWO>() {
std::printf("[two]");
}
template<> void handler<TYPE_THREE>() {
std::printf("[three]");
}
int main()
{
std::printf("== COMPILE-TIME DISPATCH ==\n");
handler<TYPE_ZERO>();
handler<TYPE_ONE>();
handler<TYPE_TWO>();
handler<TYPE_THREE>();
handler<TYPE_FOUR>();
}
And it works how I'd expect:
== COMPILE-TIME DISPATCH ==
[default][one][two][three][default]
When the message-type is known at compile time, this works great. I don't even need that ugly switch. But outside of testing I won't know the message type and even if I did, wrap_handler (for the logging) "erases" that, requiring me to use the switch "map".
void wrap_handler(MESSAGE_TYPE mt) {
std::printf("(before) ");
switch (mt) {
case TYPE_ZERO: handler<TYPE_ZERO>(); break;
case TYPE_ONE: handler<TYPE_ONE>(); break;
case TYPE_TWO: handler<TYPE_TWO>(); break;
case TYPE_THREE: handler<TYPE_THREE>(); break;
//case TYPE_FOUR: handler<TYPE_FOUR>(); break; // Showing "undefined" path
default: std::printf("(undefined)");
}
std::printf(" (after)\n");
}
int main()
{
std::printf("== RUNTIME DISPATCH ==\n");
wrap_handler(TYPE_ZERO);
wrap_handler(TYPE_ONE);
wrap_handler(TYPE_TWO);
wrap_handler(TYPE_THREE);
wrap_handler(TYPE_FOUR);
}
== RUNTIME DISPATCH ==
(before) [default] (after)
(before) [one] (after)
(before) [two] (after)
(before) [three] (after)
(before) (undefined) (after)
My "goals" for the solution are:
Have the enum value as close to the handler definition as possible -- template specialization like I show above seems to be about the best I can do in this area, but I have no idea.
When adding a message-type/handler, I'd prefer to keep the changes as local/tight as possible. (Basically, I'm looking for any way to get rid of that switch).
If I do need a switch or map, etc., since it'd be far away from the new handler, I'd like a way at compile time to tell whether there's a message type (enum value) without a corresponding switch case. (Maybe make the switch a map/array? Not sure if you can get the size of an initialized map at compile time.)
Minimize boilerplate
The other solution that seems obvious is a virtual method that's overridden in different subclasses, one for each message type, but it doesn't seem like there's a way to "bind" a message type (enum value) to a specific implementation as cleanly as the template specialization above.
Just to round it out, this could be done perfectly with (other languages) decorators:
#handles(MESSAGE_TYPE.TYPE_ZERO)
def handler(...):
...
Any ideas?
One way I'd get rid of the manual switch statements is to use template recursion, as follows. First, we create an integer sequence of your enum class, like so:
enum MESSAGE_TYPE { TYPE_ZERO, TYPE_ONE, TYPE_TWO, TYPE_THREE, TYPE_FOUR };
using message_types = std::integer_sequence<MESSAGE_TYPE, TYPE_ZERO, TYPE_ONE, TYPE_TWO, TYPE_THREE, TYPE_FOUR>;
Second, let's change slightly the handler and make it a class with a static function:
template <MESSAGE_TYPE M>
struct Handler
{
// replace with this whatever your handler needs to do
static void handle(){std::cout << (int)M << std::endl;}
};
// specialise as required
template <>
struct Handler<MESSAGE_TYPE::TYPE_FOUR>
{
static void handle(){std::cout << "This is my last message type" << std::endl;}
};
Now, with these we can easily use template recursion to create a generic switch map:
template <class Sequence>
struct ct_map;
// specialisation to end recusion
template <class T, T Head>
struct ct_map<std::integer_sequence<T, Head>>
{
template <template <T> class F>
static void call(T t)
{
return F<Head>::handle();
}
};
// recursion
template <class T, T Head, T... Tail>
struct ct_map<std::integer_sequence<T, Head, Tail...>>
{
template <template <T> class F>
static void call(T t)
{
if(t == Head) return F<Head>::handle();
else return ct_map<std::integer_sequence<T, Tail...>>::template call<F>(t);
}
};
And use as follows:
int main()
{
ct_map<message_types>::call<Handler>(MESSAGE_TYPE::TYPE_ZERO);
ct_map<message_types>::call<Handler>(MESSAGE_TYPE::TYPE_THREE);
ct_map<message_types>::call<Handler>(MESSAGE_TYPE::TYPE_FOUR);
}
If now, you want to create your wraphandler, you can do this:
template <MESSAGE_TYPE M>
struct WrapHandler
{
static void handle()
{
std::cout << "Before" << std::endl;
Handler<M>::handle();
std::cout << "After" << std::endl;
}
};
int main()
{
ct_map<message_types>::call<WrapHandler>(MESSAGE_TYPE::TYPE_THREE);
}
Live code here
The way I understand it, a function pointer may be what you need.
Going from your example, the code would be like this:
template<MESSAGE_TYPE>
void handler() {
std::printf("[default]");
}
template<> void handler<TYPE_ONE>() {
std::printf("[one]");
}
template<> void handler<TYPE_TWO>() {
std::printf("[two]");
}
template<> void handler<TYPE_THREE>() {
std::printf("[three]");
}
void wrap_handler(void (*handler)()) {
std::printf("(before) ");
if (!handler)
std::printf("(undefined)");
else
handler();
std::printf(" (after)\n");
}
int main()
{
std::printf("== COMPILE-TIME DISPATCH ==\n");
handler<TYPE_ZERO>();
handler<TYPE_ONE>();
handler<TYPE_TWO>();
handler<TYPE_THREE>();
handler<TYPE_FOUR>();
std::printf("\n\n");
std::printf("== RUNTIME DISPATCH ==\n");
wrap_handler(TYPE_ZERO);
wrap_handler(TYPE_ONE);
wrap_handler(TYPE_TWO);
wrap_handler(TYPE_THREE);
wrap_handler(TYPE_FOUR);
}
The function pointer mirrors the prototype of the function (meaning all calls need to be compatible).
In order to pass an argument, the function would change to:
void wrap_handler(void (*handler)(ArgumentType), const ArgumentType &arg) {
std::printf("(before) ");
if (!handler)
std::printf("(undefined)");
else
handler(arg);
std::printf(" (after)\n");
}
A way around this would be to use std::function (C++11).
void wrap_handler(std::function<> handler) {
std::printf("(before) ");
if (!handler)
std::printf("(undefined)");
else
handler();
std::printf(" (after)\n");
}
Possible ways to call this include:
wrap_handler(&functionWithoutArguments);
wrap_handler(std::bind(functionWithArgument, someArgument);
wrap_handler([=](){ LambdaCode; });
etc.
This is a common problem for all applications receiving messages or events.
However, in C++ the switch or some kind of table of handlers is the best you can do. The reason is that the value of the enum only exists at run-time, therefore you cannot make that decision at compile time.
Other languages, like Python, can provide the solution you are looking for, because they are interpreted languages, so compile time and run-time are the same.
Boost asio is good example of how you can hide the switch, but my experience is that hiding it is not as good as you think at the first place.
When you need to debug your code or someone else has to find the handler which belongs to a certain event, or somehow, you have to check if the handler is registered you need to know, where the switch is, place a break point there, or log the incoming messages. This is much more difficult in systems like asio.
C++ requires the exact function signature to be figured out at compile time. This does include determining template parameters. You won't be able to get rid of some logic that determines the exact operation to execute, whether you're creating a map-like data structure for this or keep it a switch. If you're just worried about accidentally leaving out some enum constant in the switch or about the boilerplate code this may be the time to get the preprocessor involved.
#ifdef MESSAGE_TYPES
# error macro name conflict for MESSAGE_TYPES may result in errors
#endif
// x is a function-like macro that takes 1 parameter (2, if you want the constants to assigned a specific value)
#define MESSAGE_TYPES(x) \
x(TYPE_ZERO) \
x(TYPE_ONE) \
x(TYPE_TWO) \
x(TYPE_THREE) \
x(TYPE_FOUR)
#ifdef MESSAGE_TYPE_ENUM_CONSTANT
# error macro name conflict for MESSAGE_TYPE_ENUM_CONSTANT may result in errors
#endif
#define MESSAGE_TYPE_ENUM_CONSTANT(c) c,
enum MESSAGE_TYPE { MESSAGE_TYPES(MESSAGE_TYPE_ENUM_CONSTANT) };
#undef MESSAGE_TYPE_ENUM_CONSTANT
template<MESSAGE_TYPE>
void handler() {
std::printf("[default]");
}
template<> void handler<TYPE_ONE>() {
std::printf("[one]");
}
template<> void handler<TYPE_TWO>() {
std::printf("[two]");
}
template<> void handler<TYPE_THREE>() {
std::printf("[three]");
}
void wrap_handler(MESSAGE_TYPE mt) {
std::printf("(before) ");
#ifdef HANDLER_CALL_SWITCH_CASE
# error macro name conflict for HANDLER_CALL_SWITCH_CASE may result in errors
#endif
#define HANDLER_CALL_SWITCH_CASE(c) case c: handler<c>(); break;
switch (mt) {
MESSAGE_TYPES(HANDLER_CALL_SWITCH_CASE);
default:
std::printf("(undefined)");
break;
}
#undef HANDLER_CALL_SWITCH_CASE
std::printf(" (after)\n");
}
#undef MESSAGE_TYPES
I have a function that takes a T and calls specific functions on the supplied object. Until now it was used from compile-time objects, so all was great. Minimal example:
#include <iostream>
struct A {
void fun() const { std::cout << "A" << std::endl; }
};
struct B {
void fun() const { std::cout << "B" << std::endl; }
};
template<class T>
void use_function(const T& param) {
param.fun();
}
int main() {
use_function(A{}); // "A"
use_function(B{}); // "B"
return 0;
}
Now I'm trying to use that use_function() with objects that get created at runtime and having a hard time. I can't use std::variant or std::any since I need to supply the type as template parameter for their access functions - although all their variants fulfil the function interface. Example for a (failing) variant approach:
using var_type = std::variant<A, B>;
struct IdentityVisitor {
template<class T>
auto operator()(const T& alternative) const -> T {
return alternative;
}
};
int main() {
var_type var = A{};
// error C2338: visit() requires the result of all potential invocations to have the same type and value category (N4828 [variant.visit]/2).
use_function(std::visit(IdentityVisitor{}, var));
return 0;
}
What is possible is directly calling the function with an appropriate type like this:
if (rand() % 2 == 0)
use_function(A{});
else
use_function(B{});
just storing it in between is what I can't get working.
I understand on a technical level but having trouble coming up with an elegant solution. Is there one? I know that I could rewrite the objects with even a lightweight inheritance - but was trying to see if it's feasible to avoid it altogether, even if just as an exercise to avoid OOP in favor of templates and concepts. I feel like variants should be working with this, but apparently not.
std::visit([](auto const& x) { use_function(x); }, var);
If overload sets were objects, you could pass use_function to std::visit directly. Because they aren't, you need to wrap it in something that will be instantiated as a call to the right overload.
std::visit([](auto const& x) { use_function(x); }, var);
I've been into C++ for some years but I have not found yet the solution to a problem I constantly have. Know how to solve it would be awesome.
What I have at the moment is:
// Client code:
switch(currentEnumValue)
{
case MyEnum::kValue01:
processData<MyEnum::kValue01>(data);
break;
case MyEnum::kValue02:
processData<MyEnum::kValue02>(data);
break;
default:
LOG("Invalid command");
break;
}
// Declarations
enum class MyEnum {kValue01, kValue02};
class MyClass
{
// code
template <MyEnum> void processData(char*); /* Implemented somewhere else */
}
template <> void MyClass::processData<MyEnum::kValue01>(char* data); /* Implemented somewhere else */
MyClass <> void MyClass::processData<MyEnum::kValue02>(char* data); /* Implemented somewhere else */
I would like to remove the switch because of many reasons. Instead of it I would need something like: processData<runtime-decltype(currentEnumValue)>(data);
I know about typeid and about not mixing compile time and runtime together... but despite this, I would like to find some solution anyway, preferably excluding macros.
This class makes a jump table for a given Enum up to a certain count size based off constructing some template and invoking it with the supplied args. It assumes the enum values start at 0, and go to Count-1.
template<class Enum, Enum Count, template<Enum>class Z>
struct magic_switch {
// return value of a call to magic_switch(Args...)
template<class...Args>
using R = std::result_of_t<Z<Enum(0)>(Args...)>;
// A function pointer for a jump table:
template<class...Args>
using F = R<Args...>(*)(Args&&...);
// Produces a single function pointer for index I and args Args...
template<size_t I, class...Args>
F<Args...> f() const {
using ret = R<Args...>;
return +[](Args&&...args)->ret{
using Invoke=Z<Enum(I)>;
return Invoke{}(std::forward<Args>(args)...);
};
}
// builds a jump table:
template<class...Args, size_t...Is>
std::array<F<Args...>,size_t(Count)>
table( std::index_sequence<Is...> ) const {
return {{
f<Is, Args...>()...
}};
}
template<class...Args>
R<Args...> operator()(Enum n, Args&&...args) {
// a static jump table for this case of Args...:
static auto jump=table<Args...>(std::make_index_sequence<size_t(Count)>{});
// Look up the nth entry in the jump table, and invoke it:
return jump[size_t(n)](std::forward<Args>(args)...);
}
};
then if you have an enum:
enum class abc_enum { a, b, c, count };
and a function object template:
template<abc_enum e>
struct stuff {
void operator()() const {
std::cout << (int)e << '\n';
}
};
you can dispatch:
magic_switch<abc_enum, abc_enum::count, stuff>{}(abc_enum::b);
in any case, within the template stuff, you get the enum value as a compile time constant. You call it with a run time constant.
Overhead should be similar to a switch statement, or a vtable call, depending on what the compiler does optimization wise.
live example.
Note that setting Enum to std::size_t is valid.
In C++11 you need make_index_sequence and index_sequence:
template<size_t...>
struct index_sequence {};
namespace details {
template<size_t Count, size_t...szs>
struct sequence_maker : sequence_maker<Count-1, Count-1, szs...> {};
template<size_t...szs>
struct sequence_maker<0,szs...> {
using type = index_sequence<szs...>;
};
}
template<size_t Count>
using make_index_sequence=typename details::sequence_maker<Count>::type;
template<class...Ts>
using index_sequence_for=make_index_sequence<sizeof...(Ts)>;
and this alias:
template<class Sig>
using result_of_t=typename std::result_of<Sig>::type;
then strip std:: off their use in the above code.
live example.
Boost variant does something like what you are doing. It lets you replace switch statements with a template based contruct that can check that all cases are defined at compile-time, but then select one at run-time.
e.g.,
using namespace boost;
using Data = variant<int, double>;
struct ProcessDataFn: static_visitor<void>
{
char* data;
void operator()(int& i)
{
// do something with data
}
void operator()(double& d)
{
// do something else
}
};
void processData(char* data, Data& dataOut)
{
apply_visitor(ProcessDataFn{data}, dataOut);
}
void example(char * data)
{
Data d = 0;
processData(data, d); // calls first overload of operator()
Data d = 0.0;
processData(data, d); // calls second overload
}
To expand on my comment, ideally we'd have compile-time reflection and be able to write a generic dispatch function. In its absence, one option is to unfortunately use macros to do that for you using the X Macro pattern:
#define LIST_OF_CASES \
X_ENUM(kValue0) \
X_ENUM(kValue1) \
X_ENUM(kValue2)
enum MyEnum
{
# define X_ENUM(a) a,
LIST_OF_CASES
# undef X_ENUM
};
void dispatch(MyEnum val)
{
switch (val)
{
# define X_ENUM(a) case a: processData<a>(); break;
LIST_OF_CASES
# undef X_ENUM
default:
// something's really wrong here - can't miss cases using this pattern
}
}
One benefit of this approach is that it scales to large numbers of enumerations, it gets really hard to omit a case, and that you can attach extra information by using a multi-argument X_ENUM macro.
I know you said you'd like to avoid macros, but the alternative without virtual functions then is to have some sort of a static table of function pointers indexed by the enum, and that is just a virtual function in disguise (with admittedly lower overhead, but still suffering the cost of an indirect function call).
Has anyone ever used pointers/references/pointer-to-member (non-type) template parameters?
I'm not aware of any (sane/real-world) scenario in which that C++ feature should be used as a best-practice.
Demonstation of the feature (for pointers):
template <int* Pointer> struct SomeStruct {};
int someGlobal = 5;
SomeStruct<&someGlobal> someStruct; // legal c++ code, what's the use?
Any enlightenment will be much appreciated!
Pointer-to-function:
Pointer-to-member-function and pointer-to-function non-type parameters are really useful for some delegates. It allows you to make really fast delegates.
Ex:
#include <iostream>
struct CallIntDelegate
{
virtual void operator()(int i) const = 0;
};
template<typename O, void (O::*func)(int)>
struct IntCaller : public CallIntDelegate
{
IntCaller(O* obj) : object(obj) {}
void operator()(int i) const
{
// This line can easily optimized by the compiler
// in object->func(i) (= normal function call, not pointer-to-member call)
// Pointer-to-member calls are slower than regular function calls
(object->*func)(i);
}
private:
O* object;
};
void set(const CallIntDelegate& setValue)
{
setValue(42);
}
class test
{
public:
void printAnswer(int i)
{
std::cout << "The answer is " << 2 * i << "\n";
}
};
int main()
{
test obj;
set(IntCaller<test,&test::printAnswer>(&obj));
}
Live example here.
Pointer-to-data:
You can use such non-type parameters to extend the visibility of a variable.
For example, if you were coding a reflexion library (which might very useful for scripting), using a macro to let the user declare his classes for the library, you might want to store all data in a complex structure (which may change over time), and want some handle to use it.
Example:
#include <iostream>
#include <memory>
struct complex_struct
{
void (*doSmth)();
};
struct complex_struct_handle
{
// functions
virtual void doSmth() = 0;
};
template<complex_struct* S>
struct csh_imp : public complex_struct_handle
{
// implement function using S
void doSmth()
{
// Optimization: simple pointer-to-member call,
// instead of:
// retrieve pointer-to-member, then call it.
// And I think it can even be more optimized by the compiler.
S->doSmth();
}
};
class test
{
public:
/* This function is generated by some macros
The static variable is not made at class scope
because the initialization of static class variables
have to be done at namespace scope.
IE:
class blah
{
SOME_MACRO(params)
};
instead of:
class blah
{
SOME_MACRO1(params)
};
SOME_MACRO2(blah,other_params);
The pointer-to-data template parameter allows the variable
to be used outside of the function.
*/
std::auto_ptr<complex_struct_handle> getHandle() const
{
static complex_struct myStruct = { &test::print };
return std::auto_ptr<complex_struct_handle>(new csh_imp<&myStruct>());
}
static void print()
{
std::cout << "print 42!\n";
}
};
int main()
{
test obj;
obj.getHandle()->doSmth();
}
Sorry for the auto_ptr, shared_ptr is available neither on Codepad nor Ideone.
Live example.
The case for a pointer to member is substantially different from pointers to data or references.
Pointer to members as template parameters can be useful if you want to specify a member function to call (or a data member to access) but you don't want to put the objects in a specific hierarchy (otherwise a virtual method is normally enough).
For example:
#include <stdio.h>
struct Button
{
virtual ~Button() {}
virtual void click() = 0;
};
template<class Receiver, void (Receiver::*action)()>
struct GuiButton : Button
{
Receiver *receiver;
GuiButton(Receiver *receiver) : receiver(receiver) { }
void click() { (receiver->*action)(); }
};
// Note that Foo knows nothing about the gui library
struct Foo
{
void Action1() { puts("Action 1\n"); }
};
int main()
{
Foo foo;
Button *btn = new GuiButton<Foo, &Foo::Action1>(&foo);
btn->click();
return 0;
}
Pointers or references to global objects can be useful if you don't want to pay an extra runtime price for the access because the template instantiation will access the specified object using a constant (load-time resolved) address and not an indirect access like it would happen using a regular pointer or reference.
The price to pay is however a new template instantiation for each object and indeed it's hard to think to a real world case in which this could be useful.
The Performance TR has a few example where non-type templates are used to abstract how the hardware is accessed (the hardware stuff starts at page 90; uses of pointers as template arguments are, e.g., on page 113). For example, memory mapped I/O registered would use a fixed pointer to the hardware area. Although I haven't ever used it myself (I only showed Jan Kristofferson how to do it) I'm pretty sure that it is used for development of some embedded devices.
It is common to use pointer template arguments to leverage SFINAE. This is especially useful if you have two similar overloads which you couldn't use std::enable_if default arguments for, as they would cause a redefinition error.
This code would cause a redefinition error:
template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
void foo (T x)
{
cout << "integral";
}
template <typename T, typename = std::enable_if_t<std::is_floating_point<T>::value>>
void foo (T x)
{
cout << "floating";
}
But this code, which utilises the fact that valid std::enable_if_t constructs collapse to void by default, is fine:
// This will become void* = nullptr
template <typename T, std::enable_if_t<std::is_integral<T>::value>* = nullptr>
void foo (T x)
{
cout << "integral";
}
template <typename T, std::enable_if_t<std::is_floating_point<T>::value>* = nullptr>
void foo (T x)
{
cout << "floating";
}
Occasionally you need to supply a callback function having a particular signature as a function pointer (e.g. void (*)(int)), but the function you want to supply takes different (though compatible) parameters (e.g. double my_callback(double x)), so you can't pass its address directly. In addition, you might want to do some work before and after calling the function.
It's easy enough to write a class template that tucks away the function pointer and then calls it from inside its operator()() or some other member function, but this doesn't provide a way to extract a regular function pointer, since the entity being called still requires the this pointer to find the callback function.
You can solve this problem in an elegant and typesafe way by building an adaptor that, given an input function, produces a customised static member function (which, like a regular function and unlike a non-static member function, can have its address taken and used for a function pointer). A function-pointer template parameter is needed to embed knowledge of the callback function into the static member function. The technique is demonstrated here.
Problem in short:
How could one implement static if functionality, proposed in c++11, in plain c++ ?
History and original problem:
Recently I came up with a problem like this. I need a class Sender with an interface like
class Sender
{
void sendMessage( ... );
void sendRequest( ... );
void sendFile( ... );
// lots of different send methods, not important actually
}
In some cases I will need to create a DoubleSender, i.e. an instance of this class, which would call its methods twice, i.e. when calling, let's say, a sendMessage(...) method, the same message has to be sent twice.
My solutions:
First approach:
Have an isDouble member, and in the end of each method call make a check
sendMessage(...) { ... if( isDouble ) { sendMessage( ... ); }
Well, I don't want this, because actually I will need double posting very recently, and this part of code in time-critical section will be 98% passive.
Second approach:
Inherit a class DoubleSender from Sender, and implement its methods like:
void DoubleSender::sendMessage( ... )
{
Sender::sendMessage(...);
Sender::sendMessage(...);
}
Well, this is acceptable, but takes much space of unpleasant code (really much, because there are lots of different send.. methods.
Third approach:
Imagine that I am using c++11 :). Then I can make this class generic and produce the necessary part of code according to tempalte argument using static if:
enum SenderType { Single, Double };
template<SenderType T>
class Sender
{
void sendMessage(...)
{
// do stuff
static if ( T == Single )
{
sendMessage(...);
}
}
};
This is shorter, easier to read than previous solutions, does not generate additional code and... it's c++11, which I unfortunately cannot use in my work.
So, here is where I came to my question - how can I implement static if analog in c++ ? Also, I would appreciate any other suggestions about how to solve my original problem.
Thanks in advance.
Quoting #JohannesSchaubLitb
with my static_if that works on gcc one can do it :)
in some limited fashion
(see also here)
This trick involves a specific GCC interpretation of the specs on Lambdas in C++11. As such, it will (likely) become a defect report against the standard. This will lead to the trick no longer working in more recent version of GCC (it already doesn't work in 4.7).
See the comment thread below for some more details from Johanness
http://ideone.com/KytVv:
#include <iostream>
namespace detail {
template<bool C>
struct call_if { template<typename F> void operator<<(F) { } };
template<>
struct call_if<true> {
template<typename F>
void operator<<(F f) { f(); }
};
}
#define static_if(cond) detail::call_if<cond>() << [&]
template<bool C, typename T>
void f(T t) {
static_if(C) {
t.foo();
};
}
int main() {
f<false>(42);
}
Why not make the send implementation a policy of the sender class and use CRTP:
template<class Derived>
class SingleSenderPolicy
{
public:
template< class memFunc >
void callWrapperImpl(memFunc f, ...)
{
static_cast<Derived *>(this)->f(...);
}
};
template< class Derived >
class DoubleSenderPolicy
{
public:
template< class memFunc >
void callWrapperImpl(memFunc f, ...)
{
static_cast<Derived *>(this)->f(...);
static_cast<Derived *>(this)->f(...);
}
};
template< class SendPolicy>
class Sender : public SendPolicy< Sender >
{
public:
void sendMessage( ... )
{
// call the policy to do the sending, passing in a member function that
// acutally performs the action
callWrapperImpl( &Sender::sendMessageImpl, ... );
}
void doSomethingElse( ... )
{
callWrapperImpl( &Sender::doSomethingElseImpl, ... );
}
protected:
void sendMessageImpl(... )
{
// Do the sending here
}
void doSomethingElseImpl(... )
{
// Do the sending here
}
};
The public sendXXX functions in you class simply forward to the call wrapper, passing in a member function that implements the real functionality. This member function will be called according to the SendPolicy of the class. CRTP saves the use of bind to wrap the arguments and this pointer up with the member function to call.
With one function it doesn't really cut down on the amount of code, but if you have a lot of calls it could help.
Note: This code is a skeleton to provide a possible solution, it has not been compiled.
Note: Sender<DoubleSenderPolicy> and Sender<SingleSenderPolicy> are completely different types and do not share a dynamic inheritance relationship.
Most compilers do constant folding and dead code removal, so if you write a regular if statement like this:
enum SenderType { Single, Double };
template<SenderType T>
class Sender
{
void sendMessage(...)
{
// do stuff
if ( T == Single )
{
sendMessage(...);
}
}
};
The if branch will get removed when the code is generated.
The need for static if is when the statements would cause a compiler error. So say you had something like this(its somewhat psuedo code):
static if (it == random_access_iterator)
{
it += n;
}
Since you can't call += on non-random access iterators, then the code would always fail to compile with a regular if statement, even with dead code removal. Because the compiler still will check the syntax for before removing the code. When using static if the compiler will skip checking the syntax if the condition is not true.
std::string a("hello world");
// bool a = true;
if(std::is_same<std::string, decltype(a)>::value) {
std::string &la = *(std::string*)&a;
std::cout << "std::string " << la.c_str() << std::endl;
} else {
bool &la = *(bool*)&a;
std::cout << "other type" << std::endl;
}