c++ - #define 中暂时使用 'reset' 命名空间

标签 c++ c++11 namespaces

我想知道是否有办法“重置”命名空间。我问这个主要是因为我想使用定义在另一个命名空间中专门化一些模板结构。

这是我可能想要实现的目标的简化示例:

namespace base {
    template<typename>
    struct my_traits;
}

// specialize base::my_traits for TYPE
// obviously, this does not work
#define MAKE_SPECIALIZED_TRAITS(TYPE)           \
    namespace ::base {                          \
        template<>                              \
        struct my_traits<TYPE> {                \
            typedef TYPE type;                  \
            enum { size = TYPE::size };         \
        };                                      \
    }

namespace spec {
    struct my_struct {
        enum { size = 3 };
    };

    MAKE_SPECIALIZED_TRAITS(my_struct)
}

这样的事可能吗?如果是这样,我将如何实现?

最佳答案

一种有趣的技术,可以使用重写和 ADL 来生成特征类。

这是伪代码,但它可能是这样的:

namespace base {
  // a template function you override in your OWN namespace to use this trick:
  template<typename T>
  void my_traits_mapping( T const& ) {};

  // SFINAE enabled internal my_traits.  if you have default traits, put them here:
  template<typename T, typename=void>
  struct my_traits_impl;

  // Detect if my_traits_mapping has been overriden for T, and if so inherit
  // my_traits_impl from its return value:
  template<typename T>
  struct my_traits_impl< T, typename std::enable_if< !std::is_same<
      void, decltype( my_traits_mapping( std::declval<T>() ) )
    >::value >::type >:
    decltype( my_traits_mapping( std::declval<T&>() ) )
  {};

  // you might want to put the above in its own sub-namespace, so as not to clutter
  // up your interface... if it is in details or aux, people will be less tempted to
  // directly mess with it.

  // forward my_traits<T> to the impl type above.
  template<typename T>
  struct my_traits : my_traits_impl<T> {};
}

我在 T 上使用 ADL调用my_traits_mapping实例为 T ,提取返回类型,并继承my_traits_impl来自它(只要它不是 void )。

现在,不再专门my_traits ,您所要做的就是创建一个函数 my_traits_mapping(X)它会在您自己的命名空间中返回一个特征类。当 my_traits<T>求值,找到这个函数,找到返回值,用它的类型构建my_traits<T> .

什么都没有离开你的namespace ,但是你神奇地将你的类型注入(inject)到特征系统中,没有向特征中注入(inject)任何东西 namespace .

摆脱namespacetemplate你的宏中的东西。相反,创建一个 my_traits_FOO输入 details命名空间,然后添加 details::my_traits_FOO my_traits_mapping( FOO const& )到您调用宏的命名空间,该命名空间应该与 FOO 相同的命名空间声明于。

关于c++ - #define 中暂时使用 'reset' 命名空间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17155814/

相关文章:

c++ - SNAP C++ 字符串类型问题 std::string 到 TStr

C++:在push_back时迭代指针 vector 时出现段错误

c++ - 正确使用 C++ 可变参数模板

c++ - 按函数名参数化模板 c++11

php - Laravel 5 从字符串生成动态对象

c++ - 如何使 "own"C++字符串类在绑定(bind)中自动转换为python字符串

c++ - 使用 libSox 链接多个效果并读取输出数据的正确方法

c++ - 一旦成为标准的一部分——boost 库会失去其 boost 命名空间并移至 std 吗?

c# - 如何在 IronPython 中调用 C#/.NET 命名空间?

vb.net - MySql.Data.MySqlClient 显示令人困惑的错误