jas*_*mar 5 c++ templates template-meta-programming
我可以专门研究前向声明的模板吗?例如:
template <typename T> class A;
template <>
class A<char> {
char a[1000];
};
int main()
{
[[maybe_unused]] A<char> a;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我想达到什么目标?
正如我们所知,我们必须专门std::hash将它与一些基于哈希表的类型一起使用。标准特化std::hash需要<functional>在头文件中包含然后特化它。我在很多地方都用到了这个头文件,编译时间<functional>挺大的。所以我想将我的专业转移到源(cpp)文件。
my_type.hpp:
class my_type {/*...*/};
namespace std {
template <typename T>
struct hash;
template <>
struct hash<my_type>
{
size_t operator()(my_type m) const;
};
} // namespace std
Run Code Online (Sandbox Code Playgroud)
my_type.cpp:
#include "my_type.hpp"
#include <functional>
namespace std {
size_t std::hash<my_type>::operator()(my_type v) const
{
return std::hash<decltype(v.value())>{}(v.value());
}
} // namespace std
Run Code Online (Sandbox Code Playgroud)
此解决方案有效,但就 ISO 标准而言是否合法?
编辑/注意:它不适用于 libc++(clang std 实现),因为它定义std::hash为std::__1::hash, where __1is inline namespace。这部分回答了这个问题。
一般的问题A是,是的,这是允许的。显式特化与主模板不相交。无论主要是如何定义的,它都可以定义为完整的或不完整的。
至于你更具体的问题std::hash,不是不行。你违反了
[命名空间.std]
1除非另有说明,如果 C++ 程序向命名空间
std或命名空间内的命名空间添加声明或定义,则它的行为是未定义的std。2除非明确禁止,否则程序可以将任何标准库类模板的模板特化添加到命名空间,
std前提是 (a) 添加的声明依赖于至少一个程序定义的类型,并且 (b) 特化满足标准库对原始模板。
前向声明std::hash不是依赖于用户定义类型的特化声明。这是属于第 1 段规范的简单声明。没有允许std::hash在标准中的任何其他地方转发声明的措辞。所以这是未定义的行为。