Can I specialize forward declared template? For example:
template <typename T> class A;
template <>
class A<char> {
char a[1000];
};
int main()
{
[[maybe_unused]] A<char> a;
return 0;
}
What do I want to achieve?
As we know, we have to specialize std::hash
to use it with some hash-table-based types. Standard std::hash
specialization requires to include <functional>
in the header file and then specialize it. I use this header file in many places, and the compilation time of <functional>
is pretty big. So I want to move my specialization to source (cpp) file.
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
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
This solution works, but is it legal in terms of ISO standard?
EDIT/NOTE: It doesn't work with libc++ (clang std implementation), because it defines std::hash
as std::__1::hash
, where __1
is inline namespace. This partially answers the question.
The general question about A
is that yes, it's allowed. An explicit specialization is disjoint from the primary template. It can be defined as complete or incomplete, regardless of how the primary is defined.
As for your more specific question about std::hash
, not it's not alright. You violate
[namespace.std]
1 Unless otherwise specified, the behavior of a C++ program is undefined if it adds declarations or definitions to namespace
std
or to a namespace within namespacestd
.2 Unless explicitly prohibited, a program may add a template specialization for any standard library class template to namespace
std
provided that (a) the added declaration depends on at least one program-defined type and (b) the specialization meets the standard library requirements for the original template.
Forward declaring std::hash
is not a declaration of a specialization that depends on a user defined type. It's a plain declaration that falls under the specification of paragraph 1. There is no wording that allows to forward declare std::hash
anywhere else in the standard. So this is undefined behavior.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With