1

I have a preprocessing code to choose which vector class is used as following:

#define USE_BOOST_VECTOR

#ifdef USE_BOOST_VECTOR
    #include <boost/container/vector.hpp>
    #define VECTOR boost::container::vector
#else
    #include <vector>
    #define VECTOR std::vector
#endif

I am not sure if this is a good way. And how about if I have more options to choose, what should I do?

Figured out if there are more options

#define USE_MY_VECTOR 1
#define USE_BOOST_VECTOR 2
#define USE_STD_VECTOR 3

#define CHOOSE_VECTOR USE_BOOST_VECTOR

#if CHOOSE_VECTOR == USE_MY_VECTOR
    #include "Vector.h"
    #define VECTOR Vector
#elif CHOOSE_VECTOR == USE_BOOST_VECTOR 
    #include <boost/container/vector.hpp>
    #define VECTOR boost::container::vector
#elif CHOOSE_VECTOR == USE_STD_VECTOR
    #include <vector>
    #define VECTOR std::vector
#endif

But I need to define 1, 2, 3, and more for more options. Just for a brain work, any better way?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
user1899020
  • 13,167
  • 21
  • 79
  • 154
  • 1
    Why not add more granularity to where this is used and accept the container type as a template argument? – GManNickG Feb 01 '13 at 00:58
  • @GManNickG The scenario seems to be that the type `VECTOR` is used throughout the whole project. Template might be not the best choice in this scenario, but a typedef would be better than macros. I mean a `using` ;) – leemes Feb 01 '13 at 01:03
  • @leemes you could even do `template using vec = std::vector;` – Rapptz Feb 01 '13 at 01:06
  • @Rapptz I meant nothing different with the "`using`". GManNickG meant something different: Accepting the vector template as a template parameter in the classes where it is used. (At least, that's how I understood it.) – leemes Feb 01 '13 at 01:07
  • @leemes your comment wasn't edited on my screen when I posted that comment, FYI. – Rapptz Feb 01 '13 at 01:11
  • @Rapptz Ah, ok. Just 1 sec after posting it, I realized that it isn't possible with `typedef`. So I added the `using`. – leemes Feb 01 '13 at 01:12
  • For all who don't know the `using` keyword: It's new in C++11 and allows a templated type alias. – leemes Feb 01 '13 at 01:14
  • 1
    Ask yourself why. Why must you be able to choose between three implementations? "Because I can" and "Because I want to" are not answers. I'd also strongly recommend against implementing your own vector unless you want to spend a lot of your future time fixing bugs in your own code. – Carl Feb 01 '13 at 01:44
  • @carleeto I agree. I prefer to std::vector, but in my profiling, boost::container::vector is much faster in my computer. Thus I set it as an option. To choose more options is just an exercise. – user1899020 Feb 01 '13 at 01:52
  • If you'd like to choose more options, then what you're after is an interface that you code against. You can then compile in different implementations of that interface and they will just work. See this for more info: http://stackoverflow.com/questions/383947/what-does-it-mean-to-program-to-an-interface – Carl Feb 01 '13 at 02:08

2 Answers2

2

Don't use pre-processor macros unless you have no other choice - typedefs, constants and if really needed, templates usually can have the intended result, while being much safer.

Now, unless you have a really good reason to prefer Boost vectors over std::vector, go with std::vector. Why? Because if you don't know what you want, what the std namespace provides should be more than enough.

EDIT: Like leemes says, you would need C++11 to make use of templated type aliases.

#define USE_BOOST_VECTOR

#ifdef USE_BOOST_VECTOR
    #include <boost/container/vector.hpp>
    template <typename T> using VECTOR = boost::container::vector<T>;
#else
    #include <vector>
    template <typename T> using VECTOR = std::vector<T>;
#endif

// ....
// You could then use it with
VECTOR<int> vec;

Finally, here is some more information on templated typedef aliases

If you don't have a C++11 compiler, you could use namespace aliases:

#define USE_BOOST_VECTOR

#ifdef USE_BOOST_VECTOR
    #include <boost/container/vector.hpp>
    namespace Container = boost::container;
#else
    #include <vector>
    namespace Container = std;
#endif

//And use it with...
Container::vector<int> vec;

I also need to add here, that the above method can lead to some very confusing results. I highly recommend that you basically decide up front which vector implementation you'd like to go with and getting rid of your pre-processor macro once and for all. Your code will thank you over time :)

Community
  • 1
  • 1
Carl
  • 43,122
  • 10
  • 80
  • 104
0

This is a bad idea, as preprocessors serve a completely different purpose than the one you are using them for. More specifically, they are used to extend the language you are working in. This could be for something as simple as making aliases to the commands in the language, or something as complicated as adding a new semantic constructs to the language, such as adding object oriented programming capability to a procedural language. At any rate, it is not to choose which class libraries to load into your program at compile-time. My suggestion would be to create an interface class, then have two classes inherit from this class. One class will act as a wrapper for boost vector and the other as a wrapper for the std::vector. This way you would not only be able to choose the implementation at compile-time (statically), but also at run-time (dynamically).

See the following link for more details: OOP a good explaination

qmckinsey
  • 305
  • 1
  • 3
  • 12