优雅地重用代码,将const添加到类实例化中

时间:2013-05-28 14:17:54

标签: c++ const c-preprocessor

我需要用两个不同的库编译相同的代码。一个允许对象是const,另一个不允许。现在实现的解决方案如下所示:

#ifdef (OLDLIB)
    ClassFoo TheFoo = Bar();
#else
    const ClassFoo TheFoo = Bar();
#endif

这对于不同的类使用了很多次并且妨碍了可读性。我想在其他地方做出区分。

我想可以说:

#ifdef (OLDLIB)
#define CLASS_FOO ClassFoo
#define CLASS_BAR ClassBar
#else
#define CLASS_FOO const ClassFoo
#define CLASS_BAR const ClassBar
#endif

CLASS_FOO TheFoo = Bar();
CLASS_BAR TheBar = FooBar();

但我不喜欢预处理器的东西。有一个不错的C ++ - 做上述的方法?感谢。

更新1: 正如Peter Wood所说,可以将它们实例化为非常量。我改了句子。

4 个答案:

答案 0 :(得分:4)

您可以使用std::conditional根据编译时变量在两种类型之间进行选择:

#ifdef OLDLIB
constexpr bool OLD = true;
#else
constexpr bool OLD = false;
#endif

std::conditional<OLD, ClassFoo, const ClassFoo>::type theFoo;
                 ~~~  ~~~~~~~~  ~~~~~~~~~~~~~~
                        true        false

从C ++ 11开始

答案 1 :(得分:3)

我很确定你已经坚持使用预处理器来实现你的目标。

但是,我可能会这样写:

#ifdef OLDLIB
#  define LIB_CONST
#else
#  define LIB_CONST const

LIB_CONST ClassFoo TheFoo(Bar());

无论哪种方式都不是超级优雅,但这样做至少意味着你只是通过预处理器而不是整个对象声明来调整对象属性。

答案 2 :(得分:1)

最简单的解决方案似乎是使用非const对象,让编译器自动在新接口所需的位置添加const。

或者你可以在预处理器块中使用typedef吗?

#ifdef (OLDLIB)
    typedef ClassFoo InstantiableFoo;
#else
    typedef const ClassFoo InstantiableFoo;
#endif

答案 3 :(得分:1)

你可以输入def

// oldlib.h
typedef ClassFoo Foo;
typedef ClassBar Bar;

// newlib.h
typedef const ClassFoo Foo;
typedef const ClassBar Bar;


// the library's user
#include "oldlib.h"       // or include "which_lib.h" that includes
                          // one of oldlib.h newlib.h
#include "your_library_that_uses_the_typedefs.h"

Foo TheFoo = Bar();
Bar TheBar = FooBar();

您可以参数化库的类和全局函数

// library.h
template <class Foo>
class SomeClass { }

template <class Foo>
Foo makeFoo() { }

// library_user.cpp

#include "library.h"
SomeClass<const ClassFoo> sc;
sc.method();
const ClassFoo f = makeFoo();

您甚至可以隐藏外部库中的Foo类型

// external_library.h
class ExternalLibrary {
     typedef const Foo foo_type;
};

ExternalLibrary::foo_type& foo_identity(const ExternalLibrary::foo_type &v) { return v; }

// your_library.h

ExternalLibrary::foo_type makeFoo() { }

foo_identity(f1);