0

I have a project which has a number of classes, some of which have alternative implementations.

I am looking for a clean way to switch between these implementations as a -D flag, without having to change every file which uses said class.

For example, I might have a class called Foo_A. It is used in a variety of locations. But I also have an alternate called Foo_B. It has some slightly different design assumptions, and might work better in some situations. It has the same interface however.

The approach that I am thinking if that when we want to use Foo_A or Foo_B, we call Foo, and whichever has been defined is the one which will be used.

This answer here suggests that using templated type aliases might be a way to go.

I made a little MWE to try and test this concept out:

main.cpp

// clang++ -std=c++14 -pedantic -Wall main.cpp -o main -v
#include "choose.h"
#include <iostream>

int main(int argc, char *argv[])
{
  Foo<int> foo;
  std::cout << foo.member() << "\n";
  return 0;
}
choose.h
#ifndef CHOOSE_H
#define CHOOSE_H

#ifdef A_SYSTEM
    #include "foo_a.h"
    template <typename T> using Foo = Foo_A<T>;
#else
    #include "foo_b.h"
    template <typename T> using Foo = Foo_B<T>;
#endif

#endif //CHOOSE_H
foo_a.h
#ifndef FOO_A_H
#define FOO_A_H

template<typename T>
class Foo_A
{
 public:
  Foo_A();
  int member()
  {
    return 4;
  };
};

#endif //FOO_A_H
foo_b.h
#ifndef FOO_B_H
#define FOO_B_H

template<typename T>
class Foo_B
{
 public:
  Foo_B();
  int member()
  {
    return 2;
  };
};

#endif //FOO_B_H

Unfortunately I am getting compile errors undefined reference to Foo_B<int>::Foo_B()'.

I haven't been a#### foo_a.h

#ifndef FOO_A_H
#define FOO_A_H

template<typename T>
class Foo_A
{
 public:
  Foo_A()
  {
    val = 4;
  };
  int member()
  {
    return 4;
  };
  int val;
};

#endif //FOO_A_H
foo_b.h
#ifndef FOO_B_H
#define FOO_B_H

template<typename T>
class Foo_B
{
 public:
  Foo_B()
  {
    val = 2;
  };
  int member()
  {
    return val;
  };
  int val;
};

#endif //FOO_B_Hble to solve this issue yet.  However, my first question is if this is a sensible design for what I'm trying to achieve?  If so, what am I doing wrong in the MWE? 

EDIT I hadn't defined my constructors, which solved the MWE problem.

foo_a.h
#ifndef FOO_A_H
#define FOO_A_H

template<typename T>
class Foo_A
{
 public:
  Foo_A()
  {
    val = 4;
  };
  int member()
  {
    return val;
  };
  int val;
};

#endif //FOO_A_H
foo_b.h
#ifndef FOO_B_H
#define FOO_B_H

template<typename T>
class Foo_B
{
 public:
  Foo_B()
  {
    val = 2;
  };
  int member()
  {
    return val;
  };
  int val;
};

#endif //FOO_B_H
Prunus Persica
  • 1,173
  • 9
  • 27
  • 3
    Your question seems to have nothing to do with macros and switching. None of your code contains any of the constructor definitions! I.e. this code would be broken even if you only had one single version of the type. – Kerrek SB Oct 08 '18 at 15:38
  • 1
    You need to define your constructor for both `Foo_A` and `Foo_B` – NathanOliver Oct 08 '18 at 15:39
  • I dont understand why so complicated. When you are fine with `#ifdef`s then why do you need the template? Just provide the two implementations and guard them with `#ifdef A_SYSTEM` – 463035818_is_not_an_ai Oct 08 '18 at 15:40
  • NathanOliver: constructors defined, which solved the issue. I think that my problem integrating this into my larger system runs deeper than this. – Prunus Persica Oct 08 '18 at 15:43
  • 1
    Please don't update your question with working code, it makes the question worthless for others as the problem asked about no longer exist. – Some programmer dude Oct 08 '18 at 15:44
  • @Someprogrammerdude unlikely that someone with the same issue will find a question with that title, but i completely agree, eg there is a dupe that would fit, but flagging it now would look weird for someone not knowing the history of the question – 463035818_is_not_an_ai Oct 08 '18 at 15:46
  • have now made clearer separation between original and edit – Prunus Persica Oct 08 '18 at 15:49

0 Answers0