2013-09-09 4 views
1

Я перемещаю часть библиотеки потоков из C++ 03 в C++ 11, но я бы хотел, чтобы она была совместима с Boost, в качестве опции для пользователей у которых нет компиляторов C++ 11. Так как C++ 11 STL и увеличить 1,54 в основном имеют один и тот же интерфейс (по крайней мере для части меня интересует), неплохо было бы иметь что-то вроде этого:Абстрактные связанные с потоком типы и методы STL и Boost

#ifdef USING_BOOST 
#define NAMESPACE boost 
#else 
#define NAMESPACE std 
#endif 

typedef NAMESPACE::mutex MyLibrary::Mutex; 
typedef NAMESPACE::condition_variable MyLibrary::ConditionVariable; 
... 

Проблема поставляется с шаблонами, например unique_lock. Лучший подход мог бы быть таким:

#define TYPEDEF(WHAT, AS) typedef LIBPREFIX::WHAT AS 

#define TYPEDEF_T(WHAT, AS)     \ 
    template <typename T>     \ 
    struct AS        \ 
    {          \ 
     typedef LIBPREFIX::WHAT<T> type; \ 
    }; 

TYPEDEF(thread, Thread); 
TYPEDEF(mutex, Mutex); 
TYPEDEF(condition_variable, ConditionVariable); 

TYPEDEF_T(lock_guard, LockGuard); 
TYPEDEF_T(unique_lock, UniqueLock); 
TYPEDEF_T(shared_ptr, SharedPtr); 

Однако я должен использовать это так:

LockGuard<Mutex>::type lock(...); 

Э.Г. Мне не нравится писать: типа все время.

Кроме того, я хотел бы переопределить make_shared функцию, т.е. отображение его следующим образом:

MyLibrary::MakeShared<T> --> NAMESPACE::make_shared<T> 

, где NAMESPACE либо «станд» или «импульс». Я думаю, что-то вроде

#define USING(WHAT) using NAMESPACE::WHAT 
USING(make_shared); 

не является жизнеспособным вариантом ... правильно?

Переопределение полного пространства имен boost не является решением, так как другие части Boost могут использоваться в коде. Какой был бы лучший способ достичь этого?

Спасибо!

+0

Помните, что библиотеки потоков в boost и C++ 11 имеют важные отличия в поведении: см. Http://stackoverflow.com/a/7242294/231299 – beerboy

ответ

0

Не самый простой вариант - использовать boost? Это позволит избежать ненужной работы для себя. В противном случае, почему бы не просто типа для тех типов, которые вы хотели бы, чтобы выбрать из одной библиотеки или другой:

namespace foo { 
#ifdef USING_BOOST 
    typedef boost::mutex  mutex; 
    typedef boost::scoped_lock mutex_lock; 
#else 
    typedef std::mutex  mutex; 
    typedef std::unique_lock mutex_lock; 
#endif 
} 

foo::mutex myMutex; 
4

Вы можете просто импортировать соответствующие имена в пространстве имен по using объявлений:

namespace MyLibrary { 

#ifdef USING_BOOST 
    using boost::thread; 
    using boost::unique_lock; 
    using boost::make_shared; 
#else 
    using std::thread; 
    using std::unique_lock; 
    using std::make_shared; 
#endif 

} 

Это работает для всех имен: классов, функций и шаблонов.

+1

. Моя основная забота об этом решении заключается в том, чтобы положить «использование» в файл заголовка, так как это может привести к конфликту имен имен с другими пространствами имен. – rippeltippel

+1

@rippeltippel: Как эти 'использование' вызывают больше проблем, чем ваши typedefs? Они оба вводят имена в пространство имен MyLibrary. – Xeo

+1

@rippeltippel Что говорит Xeo. 'using' declarations (и' use' директивы) помещают идентификаторы в область видимости. Печально известное 'unsing namespace std;' обескураженное в файлах заголовков является проблемой, потому что оно используется в глобальном пространстве имен. – Angew

1

Использование пространств имен псевдонимами:

#ifdef USING_BOOST 
namespace mt = boost; 
#else 
namespace mt = std; 
#endif 

Теперь вы можете обратиться к mt::condition_variable и компилятор будет видеть один из соответствующего пространства имен.