如何检查是否在C++中声明了一个类?

nm_*_*_tp 14 c++ c++11

我正在围绕一个框架编写一个软件,我正在使用的一个类(准确地说,扩展)在更高版本中重命名.有没有办法在C++ 11中编写一些宏/模板,以确定是否在代码中声明了具有某个名称的类?

我想要完成的一个例子如下.假设文件class_include.h包含类的定义A:

class A
{ 
...
};
Run Code Online (Sandbox Code Playgroud)

或者班级B:

class B
{ 
...
};
Run Code Online (Sandbox Code Playgroud)

和类C尝试扩展声明的那些:

#include <class_include.h>

#if (class A is declared)
class C : public A
#else // class B is declared
class C : public B
#endif
{
...
};
Run Code Online (Sandbox Code Playgroud)

注意:我想到尝试检查框架的一个版本,但这个问题的答案让我感兴趣.我也无法更改任何框架头文件.

编辑:接受的答案取决于是否定义了类(这意味着声明),在我的情况下,如果定义了类,则声明该类.

Lig*_*ica 12

除了已经给出的模板魔术思想之外,传统的方法是尽可能使用库的"版本"宏.如果没有,您不能只是更改代码并开始使用新版本的库吗?根据需要在构建系统中表示新版本的依赖项.

最终,依赖控制是软件部署过程中正常和预期的一部分.所以,即使它可能有点痛苦,我也不会过分复杂你的代码只是为了完全消除它.我的意思是你已经必须以某种形式列出库作为依赖项,所以在你开始之前你已经到了一半了!

其他答案在技术上实现了你的目标,只要我们假设"A类被定义"可以被认为等同于"A类被定义并且采取我们认为它应该采取的形式".如果没有工作依赖控制,你已经有点搞砸了,有了它你不需要黑客攻击.


Sto*_*ica 11

您可以,并且不需要任何宏.首先是观察,即使在完整定义可用之后,您也可以"转发"声明一个类.即这是有效的:

class foo{};
class foo;
Run Code Online (Sandbox Code Playgroud)

现在,借助自制程序void_t实现和is_complete类型实用程序,您可以执行以下操作:

#include <type_traits>

template<typename... Ts> struct make_void { typedef void type;};
template<typename... Ts> using void_t = typename make_void<Ts...>::type;

template <typename T, typename Enabler = void>
struct is_complete : std::false_type {};

template <typename T>
struct is_complete<T, ::void_t<decltype(sizeof(T) != 0)>> : std::true_type {};

class A;
class B;

class C : public std::conditional<is_complete<A>::value, A, B>::type {
};
Run Code Online (Sandbox Code Playgroud)

取决于是否A存在完整定义,C将继承AB公开.查看实时示例.

但我提醒说,这需要谨慎处理,否则您很可能在程序中遇到ODR违规.

  • 现在看看这个,你用相同的想法打败了整整*分钟*.我必须生锈;) (2认同)

Bat*_*eba 5

一种方法是利用 SFINAE 使用typeid它会产生与不完整类型不同的结果:

#include <iostream>
#include <typeinfo> // for typeid

template<typename T, typename = void>
constexpr bool is_defined = false;

template<typename T>
constexpr bool is_defined<T, decltype(typeid(T), void())> = true;

struct complete {}; // i.e. `complete` is defined.
struct incomplete; // not defined, just a forward declaration

int main()
{
    std::cout << is_defined<complete> << " " << is_defined<incomplete>;
}
Run Code Online (Sandbox Code Playgroud)

这需要你向前声明的类虽然,但is_defined就是constexpr它可以在编译时使用。您也可以使用,sizeof但我对空基类优化产生误报感到紧张。