0

Given that I have a function templated by an enum, I would like to "typedef/alias" the function to simplify its usage. Similar questions here: (Typedef with template functions, C++11: How to alias a function?)

Here are three possible solutions I came up with, and what I do not like about them:

  1. Write a macro wrapping the functions. Issue: macro (namespace safety?)
  2. Static function pointer. Issue: variable (e.g. need to add #pragma sections to disable Wunused-variable)
  3. Write function explicitely for each case. Issue: Creation of completely new function (i.e. not just renaming of original one), more writing prone to errors, more function calls
  4. Same as 3., but inline to keep in header. This is probably my favourite. Issue: Creation of completely new function (i.e. not just renaming of original one), more function calls

Are there other particular advantages / disadvantages of the methods listed above (apart from personal dislike)? Should some be avoided at all cost?

Dummy Example:

foo_lib.h

#ifndef _FOO_LIB_H_
#define _FOO_LIB_H_

enum class Score {
    LOSS = 0,
    DRAW = 1,
    WIN = 3
};

void AddScore(int *current_score_p, const Score &score);

template <Score SCORE>
void AddScore(int *current_score_p) {
    AddScore(current_score_p, SCORE);
}

// 1. macro
#define ADD_SCORE_DRAW(current_score_p) AddScore<Score::DRAW>((current_score_p))

// 2. static function pointer (auto would work too)
static void (*AddScoreDrawStatic)(int *current_score_p) = &AddScore<Score::DRAW>;

// 3. Explicit function for each case
void AddScoreDrawSpecial(int *current_score_p);

// 4. Like 3., but inline to keep in header
inline void AddScoreDrawInline(int *current_score_p) { AddScore<Score::DRAW>(current_score_p); }

#endif // _FOO_LIB_H_

foo_lib.cpp

#include "foo_lib.h"

void AddScore(int *current_score_p, const Score &score) {
    *current_score_p += static_cast<int>(score);
}

void AddScoreDrawSpecial(int *current_score_p) {
    AddScore<Score::DRAW>(current_score_p);
}
Cedric
  • 278
  • 1
  • 9

1 Answers1

0

If your intent is to add a score to an integer and store the result in an integer the simplest thing to do would be to make a function that can be called like so score = add_score(score, Score::DRAW); its pretty readable. Also, I hate macros.

int add_score(int previous_score, Score score);

Templating with a non type template parameter does not improve readability here in my opinion

Curious
  • 20,870
  • 8
  • 61
  • 146
  • Thanks. True, that is also what my initial function is doing (except writing to pointer vs return value). This score example here was just a code snippet to play with though, the real application I need it for is a bit more complex. – Cedric Jun 28 '17 at 08:35
  • @Cedric could you elaborate on how your real use case is more complicated then what you have presented in the question? That will probably affect my answer – Curious Jun 28 '17 at 08:36
  • I have a framework with different modules, identified by a ModuleID (enum). I then have conversion functions which would need where data comes from and where it goes to, e.g. AddData(module_id source, module_id local, data). I would like to have a version of this for each module, so I can e.g. say AddDataHome(module_id source, data) everywhere within the module "home", without having to pass it's own id everytime. – Cedric Jun 28 '17 at 08:41
  • @Cedric so why wouldn't a function like the one I have explained above work in your case? – Curious Jun 28 '17 at 08:42
  • It would work, but I would have to pass the module's own ID at every function call, which seems unnecessary. – Cedric Jun 28 '17 at 08:44