我想知道是否有办法'重置'命名空间。我主要是问这个,因为我想使用define来专门化一些模板结构。
以下是我可能希望实现的简化示例:
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)
}
这样的事情可能吗?如果是这样,我将如何实现?
答案 0 :(得分: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> {};
}
我在T
上使用ADL以my_traits_mapping
的实例调用T
,提取返回类型,并从中继承my_traits_impl
(只要它不是't void
)。
现在,您所做的只是创建一个函数my_traits
,而不是专门化my_traits_mapping(X)
,它会在您自己的命名空间中返回一个traits类。评估my_traits<T>
时,找到此函数,找到返回值,并使用其类型构建my_traits<T>
。
没有任何东西会离开你的namespace
,但你神奇地将你的类型注入到特征系统中,而没有将任何东西注入特征namespace
。
摆脱宏中的namespace
和template
内容。相反,在my_traits_FOO
命名空间中创建details
类型,然后将details::my_traits_FOO my_traits_mapping( FOO const& )
添加到您调用宏的命名空间中,该命名空间应与声明FOO
的命名空间相同
答案 1 :(得分:1)
如果您不希望在命名空间中定义名称,那么冒着听起来重复的风险(并且不打算将问题轻描淡写),请不要在命名空间中定义它。
namespace spec {
struct my_struct {
enum { size = 3 };
};
}
MAKE_SPECIALIZED_TRAITS(spec::my_struct)
顺便说一句,我在宏中省略了结束分号并将其放在使用宏的位置。这看起来对我来说更“正常”:
MAKE_SPECIALIZED_TRAITS(my_struct);
答案 2 :(得分:0)
这不起作用吗?
#define MAKE_SPECIALIZED_TRAITS(TYPE) \
template<> \
struct ::base::my_traits<TYPE> { \
typedef TYPE type; \
enum { size = TYPE::size }; \
};
更新:
我在测试中完成了这项工作:
namespace base { template struct 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)