2

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

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

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)
}

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

4

3 回答 3

2

一种有趣的技术,可以使用覆盖和 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> {};
}

我在其中使用 ADLT调用my_traits_mapping的实例T,提取返回类型,并从中继承my_traits_impl(只要不是void)。

现在,my_traits您无需专门化,而是创建一个函数,该函数my_traits_mapping(X)在您自己的命名空间中返回一个特征类。当 amy_traits<T>被求值时,这个函数被找到,返回值被找到,它的类型被用来构建my_traits<T>

什么都没有留下namespace,但你神奇地将你的类型注入到特征系统中,而不向特征注入任何东西namespace

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

于 2013-06-17T20:35:10.117 回答
1

冒着听起来重言式的风险(并且不打算轻视问题),如果您不想在命名空间中定义名称,请不要在命名空间中定义它。

namespace spec {
    struct my_struct {
        enum { size = 3 };
    };
}
MAKE_SPECIALIZED_TRAITS(spec::my_struct)

顺便说一句,我会省略宏中的结束分号并将其放在使用宏的位置。这对我来说看起来更“正常”:

MAKE_SPECIALIZED_TRAITS(my_struct);
于 2013-06-17T20:22:15.040 回答
0

这不行吗?

   #define MAKE_SPECIALIZED_TRAITS(TYPE)        \
        template<>                              \
        struct ::base::my_traits<TYPE> {        \
            typedef TYPE type;                  \
            enum { size = TYPE::size };         \
        };

更新:

我在测试中完成了这项工作:

命名空间基础 { 模板结构 my_traits; }

#define MAKE_SPECIALIZED_TRAITS(TYPE)        \
    namespace base { \
      template<>                              \
      struct my_traits<TYPE> {        \
          typedef TYPE type;                  \
          enum { size = TYPE::size };         \
      }; \
    }

namespace spec {
  struct s {
    enum { size = 10 };
    int o;
  };

}

MAKE_SPECIALIZED_TRAITS(spec::s)
于 2013-06-17T20:06:42.597 回答