问题
Suppose that I'm writing a cross-platform library, I have to organize the code in a way that there is a different behaviour for different platforms and this behaviour ( or definition ) it's choosen at compile time based on the platform where my library it's being compiled.
The "usual" way to do this in C++ is to pollute the code with a lot of #ifdef
when writing a method or a class.
The problem with approach is that:
- the source code looks really ugly
- if you are supporting 3 platforms, your source code is about 3 times larger than what you really need, meaning that your compiler still needs to parse and analyze all the code to "see" the
#ifdef
- there is no real distinctions between different implementations, it's hard to mantain when the code base is growing, and when you simply have just 3-4 platforms, it grows really fast.
Since there are a lot of new features in C++11 I was wondering if something is changed and if there are new options for this.
回答1:
You should be using your build system to do this. You should provide headers with platform-independent declarations of functions and definitions of classes. Then, depending on the target platform, the build system should compile the appropriate implementations of those functions and classes.
For example, let's consider the creation of windows for displaying graphics or GUI elements. If you're not using a library to do this, you have to write the cross-platform code yourself. First, you should think about exactly what the platform-independent interface should be. Perhaps you have a window
class and some helper functions. You could then provide the definition for that class and the declarations of the helper functions in a header file and provide separate implementations for each platform. Then you'll have a set of files like this:
window.h
window_wayland.cpp
window_winapi.cpp
window_x11.cpp
Now, all of the files that need to use your class and functions should just #include <window.h>
. They all get the same function declarations. However, you specify in the configuration of your build system that window_x11.cpp
should be compiled on systems with the X11 windowing system, window_wayland.cpp
on systems with Wayland, and window_winapi
on Windows. This means that depending on the platform you're building on, you will get an implementation of that header that works on the target platform.
This has a good few advantages:
- You've separated build concerns (which platform you're building for) from code concerns.
- Each platform-dependent implementation has its own file.
- You don't have a file cluttered with preprocessor directives and hard to follow execution paths.
This doesn't mean there's anything wrong with using defines to selectively compile different parts of your code. I prefer to see this only with small amounts of code that has been localized to the platform-dependent parts. Ideally, wrap the platform-dependent code in a function and have the #ifdef
s just swap out the implementation.
Exactly how you do this selective building depends on the build system you're using. For the GNU build system, you can achieve conditional compilation with automake. Some examples are given in the documentation. A simple example given is:
bin_PROGRAMS = hello
if LINUX
hello_SOURCES = hello-linux.c hello-common.c
else
hello_SOURCES = hello-generic.c hello-common.c
endif
Running automake
with this configuration will generate the appropriate makefile.
来源:https://stackoverflow.com/questions/15849419/c11-compile-time-polymorphism-solutions