检查类型是否来自特定名称空间

朗布拉克

我想检查类型是否来自特定的名称空间。这是我想出的:

#include <utility>

namespace helper
{
  template <typename T, typename = void>
  struct is_member_of_sample : std::false_type
  {
  };

  template <typename T>
  struct is_member_of_sample<
      T,
      decltype(adl_is_member_of_sample(std::declval<T>()))> : std::true_type
  {
  };
}

namespace sample
{
  template <typename T>
  auto adl_is_member_of_sample(T && ) -> void;
}

// -- Test it

namespace sample
{
  struct X;
}

struct Y;

static_assert(helper::is_member_of_sample<sample::X>::value, "");
static_assert(not helper::is_member_of_sample<Y>::value, "");

int main(){}

只要没有人添加adl_is_member_of_sample到自己的名称空间(甚至全局名称空间),此方法就可以正常工作当然,我必须为要测试的每个命名空间创建这样的构造。

有没有一种更好的方法可以在编译时检查类型是否来自特定名称空间?


基本原理 或“我为什么要这样”:

在EDSL中,我在编译时检查类型特征,以查看某些表达式是否有效。其中一些类型特征非常简单:如果类具有using is_numeric = void,则将其视为数字表达式。工作正常。

is_numeric虽然很通用。其他人也可以使用它。因此,我考虑过通过检查类型是否来自预期名称空间来支持trait。

堆垛机

有一种(特定于编译器的)方法可以测试某个类型是否在某个命名空间中,但是我将让您决定它是否比您的类型更好:

#include <utility>
#include <type_traits>

namespace helper
{
class ctstring
{
public:
  constexpr ctstring(const char* string) : _string(string)
  {
  }

  constexpr const char* c_str() const
  {
    return _string;
  }

  constexpr bool begins_with(const ctstring other) const
  {
    return !*other.c_str() ||
           (*_string && *_string == *other.c_str() &&
            ctstring(_string + 1).begins_with(other.c_str() + 1));
  }

private:
  const char* _string;
};

template <typename T>
constexpr bool is_type_in_namespace(const ctstring name)
{
#if defined(_MSC_VER)
#define PRETTY_FUNCTION_OFFSET_1 \
  (sizeof("void __cdecl helper::is_type_in_namespace<struct ") - 1)
#define PRETTY_FUNCTION_OFFSET_2 \
  (sizeof("void __cdecl helper::is_type_in_namespace<class ") - 1)

  return ctstring(__FUNCSIG__ + PRETTY_FUNCTION_OFFSET_1).begins_with(name) ||
         ctstring(__FUNCSIG__ + PRETTY_FUNCTION_OFFSET_2).begins_with(name);

#undef PRETTY_FUNCTION_OFFSET_1
#undef PRETTY_FUNCTION_OFFSET_2
#elif defined(__clang__)
  return ctstring(__PRETTY_FUNCTION__ +
                  (sizeof("bool helper::is_type_in_namespace(const "
                          "helper::ctstring) [T = ") -
                   1))
    .begins_with(name);
#elif defined(__GNUC__)
  return ctstring(__PRETTY_FUNCTION__ +
                  (sizeof("constexpr bool "
                          "helper::is_type_in_namespace(helper::ctstring) "
                          "[with T = ") -
                   1))
    .begins_with(name);
#else
#error "Your compiler is not supported, yet."
#endif
}
}

// -- Test it

namespace sample
{
struct True_X;

class True_Y;

template <typename>
class True_T;

template <typename A>
using True_U = True_T<A>;
}

struct False_X;

class False_Y;

template <typename>
class False_T;

template <typename A>
using False_U = False_T<A>;

void test1()
{
  static_assert(helper::is_type_in_namespace<sample::True_X>("sample::"), "1");
  static_assert(helper::is_type_in_namespace<sample::True_Y>("sample::"), "2");
  static_assert(helper::is_type_in_namespace<sample::True_T<int>>("sample::"), "3");
  static_assert(helper::is_type_in_namespace<sample::True_U<int>>("sample::"), "4");
  static_assert(!helper::is_type_in_namespace<False_X>("sample::"), "5");
  static_assert(!helper::is_type_in_namespace<False_Y>("sample::"), "6");
  static_assert(!helper::is_type_in_namespace<False_T<int>>("sample::"), "7");
  static_assert(!helper::is_type_in_namespace<False_U<int>>("sample::"), "8");
}

namespace sample
{
void test2()
{
  static_assert(helper::is_type_in_namespace<True_X>("sample::"), "1");
  static_assert(helper::is_type_in_namespace<True_Y>("sample::"), "2");
  static_assert(helper::is_type_in_namespace<True_T<int>>("sample::"), "3");
  static_assert(helper::is_type_in_namespace<True_U<int>>("sample::"), "4");
  static_assert(!helper::is_type_in_namespace<::False_X>("sample::"), "5");
  static_assert(!helper::is_type_in_namespace<::False_Y>("sample::"), "6");
  static_assert(!helper::is_type_in_namespace<::False_T<int>>("sample::"), "7");
  static_assert(!helper::is_type_in_namespace<::False_U<int>>("sample::"), "8");
}

namespace inner
{
void test3()
{
  static_assert(helper::is_type_in_namespace<::sample::True_X>("sample::"), "1");
  static_assert(helper::is_type_in_namespace<::sample::True_Y>("sample::"), "2");
  static_assert(helper::is_type_in_namespace<::sample::True_T<int>>("sample::"), "3");
  static_assert(helper::is_type_in_namespace<::sample::True_U<int>>("sample::"), "4");
  static_assert(!helper::is_type_in_namespace<::False_X>("sample::"), "5");
  static_assert(!helper::is_type_in_namespace<::False_Y>("sample::"), "6");
  static_assert(!helper::is_type_in_namespace<::False_T<int>>("sample::"), "7");
  static_assert(!helper::is_type_in_namespace<::False_U<int>>("sample::"), "8");
}
}
}

void test4()
{
  using namespace sample;

  static_assert(helper::is_type_in_namespace<True_X>("sample::"), "1");
  static_assert(helper::is_type_in_namespace<True_Y>("sample::"), "2");
  static_assert(helper::is_type_in_namespace<True_T<int>>("sample::"), "3");
  static_assert(helper::is_type_in_namespace<True_U<int>>("sample::"), "4");
}

int main(int argc, char* argv[])
{
  test1();
  sample::test2();
  sample::inner::test3();
  test4();
  return 0;
}

我为MSVC2015和一些随机的在线Clang编译器以及GCC 6.1.0进行了测试。

想法:

  • 该测试接受名称空间样本和任何子命名空间中的类和结构。
  • 它不会遭受您解决方案的弊端
  • 您可能想要在std :: decay_t中构建以删除CV限定词。
  • 显然,代码需要> = C ++ 14编辑:再也没有了,C ++ 11就足够了
  • 没人喜欢宏编辑:删除了大多数宏
  • 该代码不是很容易移植,对于某些编译器和编译器版本,很可能需要其他分支。解决方案是否可接受取决于您的要求

编辑:重构代码使其更清晰并添加了GCC支持。此外,现在可以将要测试的名称空间作为参数传递

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

jQuery检查输入是否具有特定名称?

来自分类Dev

检查是否正在运行具有特定名称的特定文件?

来自分类Dev

仅解决来自指定名称空间的依赖项

来自分类Dev

如何使用jQuery检查是否存在具有特定名称attr的输入

来自分类Dev

使用JAVA检查指定的XML元素是否具有特定名称

来自分类Dev

仅在特定名称空间下自动映射

来自分类Dev

在T在特定名称空间中的地方注册通用

来自分类Dev

在特定名称空间C#中打印枚举列表

来自分类Dev

Clojure:在特定名称空间中启动repl

来自分类Dev

为每个用户授予对特定名称空间的特权

来自分类Dev

查找范围为特定名称空间(模块)的常量(类)

来自分类Dev

在特定名称空间C#中打印枚举列表

来自分类Dev

仅在特定名称空间下自动映射

来自分类Dev

如何使用SimpleInjector获取特定名称空间的实例?

来自分类Dev

来自对象的ArrayList和对象的特定名称

来自分类Dev

检查指定名称的数组是否包含指定值的函数

来自分类Dev

检查指定名称的数据库是否存在

来自分类Dev

取消绑定除特定名称空间之外的所有名称空间的事件

来自分类Dev

取消绑定除特定名称空间之外的所有名称空间的事件

来自分类Dev

选择特定名称和输入类型Jquery

来自分类Dev

检查类型是否属于没有硬编码字符串的名称空间

来自分类Dev

如果代表stdin,“-”是否有特定名称?

来自分类Dev

GHCI是否要求类型或值名称空间?

来自分类Dev

检查字段是否来自特定类别

来自分类Dev

检查工作簿中的工作表是否具有特定名称,如果有,请对其进行更改

来自分类Dev

在两个引用的程序集中出现的引用特定名称空间

来自分类Dev

拦截特定名称空间中的所有方法/构造函数/获取器/设置器

来自分类Dev

如何在C#中调用特定名称空间的函数

来自分类Dev

如何为所有Kubernetes服务帐户授予对特定名称空间的访问权限?

Related 相关文章

  1. 1

    jQuery检查输入是否具有特定名称?

  2. 2

    检查是否正在运行具有特定名称的特定文件?

  3. 3

    仅解决来自指定名称空间的依赖项

  4. 4

    如何使用jQuery检查是否存在具有特定名称attr的输入

  5. 5

    使用JAVA检查指定的XML元素是否具有特定名称

  6. 6

    仅在特定名称空间下自动映射

  7. 7

    在T在特定名称空间中的地方注册通用

  8. 8

    在特定名称空间C#中打印枚举列表

  9. 9

    Clojure:在特定名称空间中启动repl

  10. 10

    为每个用户授予对特定名称空间的特权

  11. 11

    查找范围为特定名称空间(模块)的常量(类)

  12. 12

    在特定名称空间C#中打印枚举列表

  13. 13

    仅在特定名称空间下自动映射

  14. 14

    如何使用SimpleInjector获取特定名称空间的实例?

  15. 15

    来自对象的ArrayList和对象的特定名称

  16. 16

    检查指定名称的数组是否包含指定值的函数

  17. 17

    检查指定名称的数据库是否存在

  18. 18

    取消绑定除特定名称空间之外的所有名称空间的事件

  19. 19

    取消绑定除特定名称空间之外的所有名称空间的事件

  20. 20

    选择特定名称和输入类型Jquery

  21. 21

    检查类型是否属于没有硬编码字符串的名称空间

  22. 22

    如果代表stdin,“-”是否有特定名称?

  23. 23

    GHCI是否要求类型或值名称空间?

  24. 24

    检查字段是否来自特定类别

  25. 25

    检查工作簿中的工作表是否具有特定名称,如果有,请对其进行更改

  26. 26

    在两个引用的程序集中出现的引用特定名称空间

  27. 27

    拦截特定名称空间中的所有方法/构造函数/获取器/设置器

  28. 28

    如何在C#中调用特定名称空间的函数

  29. 29

    如何为所有Kubernetes服务帐户授予对特定名称空间的访问权限?

热门标签

归档