2013-09-26 45 views
3

我正在努力为我一直在努力的类型族提供hash<>专业化。到目前为止,专业化本身很容易提供,我已经为numeric_limits<>做过类似的事情。但是我正面临着如何为C++ 11和-pre-11(C++ 03或其他)提供专门化的问题,即portable专门化名称空间中的模板 - 命名空间别名真的是别名吗?

我碰到的问题当然是hash<>可以用几种名称空间中的一种来定义,我不得不在相同的名称空间中提供专门化。

// in c++11 
namespace std { struct hash<>...; } 
// in c++03 this is one possibility 
namespace std { namespace tr1 { struct hash<>...; } } 

// my library's specialization 
namespace ????_open { 
struct hash<mytype>...; 
????_close 

当然,其中一个方案是使用#define语句来达到,打开和关闭足够的命名空间,或提供与N个不同的专长N档和有条件#包括正确的,但是这是很麻烦:

#if defined(some_c++11_condition) 
    #include "c++11-specialization.h" 
#elif defined(some_c++03_condition) 
    #include "c++03-specialization.h" 
#elif (some_other_condition) 
    #oh_dear_who_knows_what_this_include_will_be_like 
#else_ad_nauseam 
#endif 

当然,如果我被迫到,我会坚持这个策略,但我想探索一些其他的选择。特别是,我虽然我可以用namespace alias专注于正确的位置:

#if defined(some_c++11_condition) 
    namespace std_specialize = std; 
#elif defined(some_c++03_condition) 
    namespace std_specialize = std::tr1; 
#... 
#endif 

... 

namespace std_specialize { 
struct hash<mytype>...; 
} 

不幸的是,这并不在任何3个编译器我已经试过的工作(MSVC 2008年,GCC 4.7,锵3.0)在重新打开命名空间的行中有关于“declaration of namespace conflicts with...”的各种错误,这不应该发生,因为命名空间可以重新打开多次,并且如果别名是别名而不是别的,那么这也应该适用于它们。

那么,是一个命名空间别名真的是的别名,还是一个用词不当的意思?或者还有其他的原因,为什么我不能专注于这种方式?如果是这样,还有其他方法(比#defines的barrages更好)?

回答

1

是的,一个namespace别名实际上是一个别名。发生此错误的原因是您声明std_specialize作为stdstd::tr1的别名,然后尝试声明具有相同名称的namespace。如果它是合法的,那么在声明之后,std_specialize将引用什么,std(或std::tr1)或包含您的hash专业化的新名称空间?

你可能想要做什么是

namespace std { 
#if __cplusplus < 201103L 
namespace tr1 { 
#endif 

template<> 
struct hash<my_type> { ... }; 

#if __cplusplus < 201103L 
} 
#endif 
} 
+0

是否真的试图_declare_一个新的命名空间?名称空间'std_specialize'已经存在,作为另一个的别名,所以声明应该重新打开现有的名称空间。标准中是否考虑到这种情况,解析问题还是什么? –

+0

@Luis我意识到这就是你想要它的意思,但那不是它实际上在做什么:)。你正试图在这种情况下声明一个新的名字空间。我不知道不允许你解释的技术原因是什么。 – Praetorian

+0

我明白了,谢谢你的细节。 –

0

正确的宏:

// Defined before 
// #define NOEXCEPT noexcept 

#include <iostream> 

#if TR1_CONDITION 
// tr1 
    #define HASH_NAMESPACE std::tr1 
    #define HASH_NAMESPACE_BEGIN namespace std { namespace tr1 { 
    #define HASH_NAMESPACE_END }} 
#else 
// std 
    #define HASH_NAMESPACE std 
    #define HASH_NAMESPACE_BEGIN namespace std { 
    #define HASH_NAMESPACE_END } 
#endif 

namespace X { 
    struct Class {}; 
} 

HASH_NAMESPACE_BEGIN 
    template<> 
    struct hash<X::Class> { 
     size_t operator()(const X::Class&) const NOEXCEPT { return 123; } 
    }; 
HASH_NAMESPACE_END 

int main() { 
    HASH_NAMESPACE::hash<X::Class> h; 
    std::cout << h(X::Class()) << std::endl; 
    return 0; 
} 

(但是这一切是不是很好)

+0

对于C++ 03,“noexcept”是否有效(即忽略),还是必须将其删除? –

+0

@LuisMachuca是不是 –