Specializing std::hash to derived classes - c++11

I have an abstract base class Hashable that classes that can be hashed derive from. I would now like to extend std::hash to all classes that derive from Hashable.
The following code is supposed to do exactly that.
#include <functional>
#include <type_traits>
#include <iostream>
class Hashable {
public:
virtual ~Hashable() {}
virtual std::size_t Hash() const =0;
};
class Derived : public Hashable {
public:
std::size_t Hash() const {
return 0;
}
};
// Specialization of std::hash to operate on Hashable or any class derived from
// Hashable.
namespace std {
template<class C>
struct hash {
typename std::enable_if<std::is_base_of<Hashable, C>::value, std::size_t>::type
operator()(const C& object) const {
return object.Hash();
}
};
}
int main(int, char**) {
std::hash<Derived> hasher;
Derived d;
std::cout << hasher(d) << std::endl;
return 0;
}
The above code works exactly as expected with gcc 4.8.1, but when I try to compile it with gcc 4.7.2, I get the following:
$ g++ -std=c++11 -o test test_hash.cpp
test_hash.cpp:22:8: error: redefinition of ‘struct std::hash<_Tp>’
In file included from /usr/include/c++/4.7/functional:59:0,
from test_hash.cpp:1:
/usr/include/c++/4.7/bits/functional_hash.h:58:12: error: previous definition of ‘struct std::hash<_Tp>’
/usr/include/c++/4.7/bits/functional_hash.h: In instantiation of ‘struct std::hash<Derived>’:
test_hash.cpp:31:24: required from here
/usr/include/c++/4.7/bits/functional_hash.h:60:7: error: static assertion failed: std::hash is not specialized for this type
Can anybody think of a way to make this specialization of std::hash work for any class derived from Hashable with gcc 4.7.2?

It seems like there is no proper way to do what I wanted to do. I have decided to just write separate specializations for each derived class, using the following macro:
// macro to conveniently define specialization for a class derived from Hashable
#define DEFINE_STD_HASH_SPECIALIZATION(hashable) \
namespace std { \
template<> \
struct hash<hashable> { \
std::size_t operator()(const hashable& object) const { \
return object.Hash(); \
} \
}; \
}
and then
// specialization of std::hash for Derived
DEFINE_STD_HASH_SPECIALIZATION(Derived);

Related

CRTP traits only working with templated derived class

I have seen an idiom for using Derived type traits in the base class of a CRTP pattern that looks like this:
template<typename Derived>
struct traits;
template<typename Derived>
struct Base {
using size_type = typename traits<Derived>::size_type;
};
template <typename T>
struct Derived1 : Base<Derived1<T>>{
using size_type = size_t;
void print(){ std::cout << "Derived1" << std::endl; }
};
template <typename T>
struct traits<Derived1<T>> {
using size_type = size_t;
};
int main()
{
using T = float;
Derived1<T> d1;
d1.print();
}
My understanding is that the purpose of the idiom is to delay the instantiation of the Base class's size_type. What I am confused by is the fact that this pattern only seems to work if the derived class is itself templated. For instance, if we change the code to:
template<typename Derived>
struct traits;
template<typename Derived>
struct Base {
using size_type = typename traits<Derived>::size_type;
};
struct Derived1 : Base<Derived1>{
using size_type = size_t;
void print(){ std::cout << "Derived1" << std::endl; }
};
template <>
struct traits<Derived1> {
using size_type = size_t;
};
int main()
{
Derived1 d1;
d1.print();
}
then we get the error
prog.cc: In instantiation of 'struct Base<Derived1>':
prog.cc:21:19: required from here
prog.cc:18:58: error: invalid use of incomplete type 'struct traits<Derived1>'
using size_type = typename traits<Derived>::size_type;
^
prog.cc:14:8: note: declaration of 'struct traits<Derived1>'
struct traits;
^~~~~~
prog.cc: In function 'int main()':
prog.cc:33:9: error: 'Derived1' is not a template
Derived1<float> d1;
Could somebody give me an explanation indicating why the templated derived class compiles, but the untemplated class does not?
The issue you're seeing has nothing to do with CRTP.
Here's what the standard mentions.
If a class template has been declared, but not defined, at the point of instantiation (13.7.4.1),
the instantiation yields an incomplete class type (6.7). [Example:
template<class T> class X; X<char> ch; // error: incomplete type
X<char>
Your traits has only been declared at the point of instantiation of Base<Derived>, hence as per the standard(see above extraction from the standard), struct traits<Derived> yields an incomplete type.
You should reorder the code so that it sees the traits<Derived> specialization when Base<Derived> gets instantiated.
The compilation error you are seeing has nothing to do with CRTP, it's just a bit of a mish-mash of dependencies.
In the code without the templation, your "Base" struct needs the definition of the specialized "traits" struct but it only appears afterwards, so it tries to use the incomplete type it saw in the declaration above.
To get the code to work you need to have the "traits" specialization before the Base declaration, which requires you to also add a declaration of Derived 1, here is a compiling code:
class Derived1;
template<typename Derived>
struct traits;
template <>
struct traits<Derived1> {
using size_type = size_t;
};
template<typename Derived>
struct Base {
using size_type = typename traits<Derived>::size_type;
};
struct Derived1 : Base<Derived1>{
using size_type = size_t;
void print(){ std::cout << "Derived1" << std::endl; }
};
int main()
{
Derived1 d1;
d1.print();
}

Why does failed enable_if lead to compile time error?

I want to disable copy constructor of some template class conditionally. In other words, I want disable copy constructor, if base type is not copy constructible. To solve such problem (in educational purposes) I decided to write following program. (Here is link to ideone https://ideone.com/QY0NHJ) Below is source of my program:
#include <algorithm>
#include <type_traits>
using namespace std;
template <typename Data>
class Container
{
public:
typedef Container<Data> self_type;
Container():
m_data()
{
}
Container(const typename
std::enable_if<std::is_copy_constructible<Data>::value,
self_type>::type& other_data) :
m_data(other_data.m_data)
{
}
Container(self_type&& other)
{
std::swap(m_data, other.m_data);
}
private:
Data m_data;
};
class SomeData
{
public:
SomeData(){}
SomeData(const SomeData&) = delete;
};
int main()
{
Container<SomeData> container;
return 0;
}
But message from compiler really confuses me:
prog.cpp: In instantiation of ‘class Container’:
prog.cpp:41:22: required from here
prog.cpp:17:2: error: no type named ‘type’ in ‘struct std::enable_if >’
Container(const typename std::enable_if::value
As I understand it should lead to SFINAE and nothing should be arised from compiler. Where am I wrong?
As I understand it should lead to SFINAE
SFINAE means "substitution failure is not an error". You need substitution to occur in order to SFINAE out something. In this case, it is sufficient to add a default template parameter to your copy constructor:
template <typename D = Data>
Container(const typename std::enable_if<std::is_copy_constructible<D>::value,
self_type>::type& other_data) :
m_data(other_data.m_data)
{
}
live example on wandbox

How to make a particular constructor on a tempate type available only for a particular specialization in C++11?

I have a C++11 template that can be specialized with an arbitrary type parameter.
template<class ElementType>
class Foo
How do I declare a constructor that appears for the compiler's consideration only when ElementType is e.g. const uint8_t?
That is, I have a bunch of constructors that are generic over any ElementType, but I also want to have constructors that are only considered when ElementType is specialized in a particular way. (Allowing those constructors to be selected for other types would be unsafe.)
So far std::enable_if examples that I've found have been conditional on the types of the arguments of the constructors.
template<class ElementType>
struct Foo
{
template <typename T = ElementType>
Foo(typename std::enable_if<!std::is_same<T, const uint8_t>{}>::type* = nullptr) {}
template <typename T = ElementType>
Foo(typename std::enable_if<std::is_same<T, const uint8_t>{}>::type* = nullptr) {}
};
int main()
{
Foo<int> a{}; // ok, calls first constructor
Foo<const uint8_t> b{}; // ok, calls second constructor
}
wandbox example
You can break the class into two classes. The derived class' purpose is to be able to specialize constructors for different types. E.g.:
#include <cstdio>
#include <cstdint>
template<class ElementType>
struct Foo_
{
Foo_() { std::printf("%s\n", __PRETTY_FUNCTION__); }
};
template<class ElementType>
struct Foo : Foo_<ElementType>
{
using Foo_<ElementType>::Foo_; // Generic version.
};
template<>
struct Foo<uint8_t> : Foo_<uint8_t>
{
Foo() { std::printf("%s\n", __PRETTY_FUNCTION__); } // Specialization for uint8_t.
};
int main(int ac, char**) {
Foo<int8_t> a;
Foo<uint8_t> b;
}
The benefit of using the derived class here compared to enable_if is that:
The class can be partially specialized.
Only one specialization of the class is chosen for particular template parameters, rather than a set of constructors. When adding specializations for new types the existing enable_if expressions may need to be changed to make them more restrictive to avoid function overload set resolution ambiguity.

protected members in a template deduction context: compilation error, substitution fails, or succeeds?

g++ 5.2.1 fails to compile when it encounters a private method's address in a template deduction context whereas clang 3.5 only discards the specialization.
g++ 5.2.1 can access protected members of parents/friends in a class template parameter list when clang 3.5 sometimes fail to do so.
Which are wrong in which cases?
More precisely:
Should the compiler cause a hard error when trying to access a non accessible protected/private member in a template deduction context? Am I doing something wrong in my first example?
If not, should the compiler discard a specialization when trying to access (in a template deduction context) a protected member owned by:
a base class of this specific specialization
a class which declared this specific instantiation as a friend
a friend class which declared any instantiation of this template as a friend
The first question seems to have already been answered here (and the answer seems to be "no, the code isn't ill-formed and the compiler should simply discard this specialization"). However, since it's a prerequisite to the second question (and g++ 5.2.1 doesn't seem to agree), I want to be absolutely sure that it's g++ 5.2.1 which is wrong, not me.
Longer version with examples
I would like to make traits able to detect whether some functions/methods are implemented, even if they are protected members of some class (if you find this odd, I'll explain why I want to do this at the end of this question so that you can tell me I'm completely wrong, should learn how to design my classes, and maybe suggest me a cleaner way to do so).
My problem is that each of my attempts fail on either clang or g++ (oddly enough, not both at the same time): Sometimes it compiles but don't provide the expected result, sometimes it doesn't compile at all.
Even though it seems it isn't practical, I at least want to know when the compilers are faulty, and when I'm writing ill-formed code. Hence this question.
I use the C++11 dialect, and my clang version is actually the compiler provided with XCode 5 i.e. Apple LLVM version 6.0 (clang-600.0.57) (based on LLVM 3.5svn).
To better illustrate what my problem is, here is a minimal exemple where clang compiles but g++ 5.2.1 doesn't:
#include <iostream>
#include <type_traits>
#include <utility>
struct PrivateFoo {
private:
void foo() {}
};
/* utilities */
// reimplement C++17's std::void_t
template<class...>
struct void_type {
typedef void type;
};
template<class... T>
using void_t = typename void_type<T...>::type;
// dummy class used to check whether a pointer to (possibly member) function
// exists with the good signature
template<class T, T>
struct check_signature {};
/* traits */
template<class C, class = void>
struct has_foo : std::false_type {};
template<class C>
struct has_foo<C, void_t<check_signature<void(C::*)(), &C::foo>>> :
std::true_type {};
int main() {
std::cout << std::boolalpha;
std::cout << "PrivateFoo has foo: " << has_foo<PrivateFoo>::value << '\n';
return 0;
}
output with clang 3.5:
PrivateFoo has foo: false
g++ 5.2.1 errors:
access_traits.cpp : [in instantiation of] ‘struct has_foo<PrivateFoo>’ :
access_traits.cpp:37:61: required from here
access_traits.cpp:7:8: [error]: ‘void PrivateFoo::foo()’ is private
void foo() {}
^
access_traits.cpp:32:56: [error]: [in context]
struct has_foo<C, void_t<check_signature<void(C::*)(), &C::foo>>> :
^
access_traits.cpp:7:8: [error]: ‘void PrivateFoo::foo()’ is private
void foo() {}
^
access_traits.cpp:32:56: [error]: [in context]
struct has_foo<C, void_t<check_signature<void(C::*)(), &C::foo>>> :
^
access_traits.cpp: [in function] ‘int main()’:
access_traits.cpp:7:8: erreur: ‘void PrivateFoo::foo()’ is private
void foo() {}
^
access_traits.cpp:37:42: [error]: [in context]
std::cout << "PrivateFoo has foo: " << has_foo<PrivateFoo>::value << '\n';
(text in brackets is translated, it was originally in my native language)
Here is an example where both compile but disagree on whether foo is accessible or not:
#include <iostream>
#include <type_traits>
#include <utility>
struct ProtectedFoo {
protected:
void foo() {}
};
/* utilities */
// reimplement C++17's std::void_t
template<class...>
struct void_type {
typedef void type;
};
template<class... T>
using void_t = typename void_type<T...>::type;
// dummy class used to check whether a pointer to (possibly member) function
// exists with the good signature
template<class T, T>
struct check_signature {};
/* traits */
namespace detail {
template<class C, class = void>
struct has_foo_helper : std::false_type {};
template<class C>
struct has_foo_helper<C, void_t<decltype(std::declval<C>().foo())>> :
std::true_type {};
}
template<class C>
struct has_public_or_protected_foo : protected C {
template<class, class>
friend class detail::has_foo_helper;
static constexpr bool value =
detail::has_foo_helper<has_public_or_protected_foo<C>>::value;
};
int main() {
std::cout << std::boolalpha;
std::cout << "ProtectedFoo has foo: ";
std::cout << has_public_or_protected_foo<ProtectedFoo>::value << '\n';
return 0;
}
output with clang 3.5:
ProtectedFoo has foo: false
output with g++ 5.2.1:
ProtectedFoo has foo: true
and finally here is an example where both compile and agree that they should be able to access foo:
#include <iostream>
#include <type_traits>
#include <utility>
struct ProtectedFoo {
protected:
void foo() {}
};
/* utilities */
// reimplement C++17's std::void_t
template<class...>
struct void_type {
typedef void type;
};
template<class... T>
using void_t = typename void_type<T...>::type;
// dummy class used to check whether a pointer to (possibly member) function
// exists with the good signature
template<class T, T>
struct check_signature {};
/* traits */
namespace detail {
template<class C, class D, class = void>
struct has_foo_helper : std::false_type {};
template<class C, class D>
struct has_foo_helper<C, D, void_t<check_signature<void(C::*)(), &D::foo>>> :
std::true_type {};
}
template<class C>
struct has_public_or_protected_foo : protected C {
template<class, class, class>
friend class detail::has_foo_helper;
static constexpr bool value =
detail::has_foo_helper<C, has_public_or_protected_foo<C>>::value;
};
int main() {
std::cout << std::boolalpha;
std::cout << "ProtectedFoo has foo: ";
std::cout << has_public_or_protected_foo<ProtectedFoo>::value << '\n';
return 0;
}
output with clang 3.5:
ProtectedFoo has foo: true
output with g++ 5.2.1:
ProtectedFoo has foo: true
Also here is a more complete example which summarizes it all:
#include <iostream>
#include <type_traits>
#include <utility>
/* test classes */
struct PublicFoo {
void foo() {}
};
struct ProtectedFoo {
protected:
void foo() {}
};
struct PrivateFoo {
private:
void foo() {}
};
struct NoFoo {};
/* utilities */
// reimplement C++17's std::void_t
template<class...>
struct void_type {
typedef void type;
};
template<class... T>
using void_t = typename void_type<T...>::type;
// dummy class used to check whether a pointer to (possibly member) function
// exists with the good signature
template<class T, T>
struct check_signature {};
/* traits */
namespace detail {
template<class C, class D, class = void>
struct has_foo_helper : std::false_type {};
template<class C, class D>
struct has_foo_helper<C, D, void_t<check_signature<void(C::*)(), &D::foo>>> :
std::true_type {};
template<class C, class = void>
struct may_call_foo_helper : std::false_type {};
template<class C>
struct may_call_foo_helper<C, void_t<decltype(std::declval<C>().foo())>> :
std::true_type {};
}
template<class C>
struct has_foo : detail::has_foo_helper<C, C> {};
template<class C>
struct may_call_foo : detail::may_call_foo_helper<C> {};
template<class C>
struct has_protected_foo : protected C {
template<class, class, class>
friend class detail::has_foo_helper;
static constexpr bool value =
detail::has_foo_helper<C, has_protected_foo<C>>::value;
};
template<class C>
struct may_call_protected_foo : protected C {
template<class, class>
friend class detail::may_call_foo_helper;
static constexpr bool value =
detail::may_call_foo_helper<may_call_protected_foo<C>>::value;
};
/* test */
template<class T>
void print_info(const char* classname) {
std::cout << classname << "...\n";
// comment this if you want to compile with g++
//*
std::cout << "has a public method \"void foo()\": ";
std::cout << has_foo<T>::value << '\n';
std::cout << "has a public or protected method \"void foo()\": ";
std::cout << has_protected_foo<T>::value << '\n';
//*/
std::cout << "has a public method \"foo\" callable without any arguments: ";
std::cout << may_call_foo<T>::value << '\n';
std::cout << "has a public or protected method \"foo\" callable without any "
"arguments: ";
std::cout << may_call_protected_foo<T>::value << '\n';
std::cout << '\n';
}
int main() {
std::cout << std::boolalpha;
// both g++ 5.2.1 and clang 3.5 compile
print_info<PublicFoo>("PublicFoo");
// g++ 5.2.1 fails to compile has_foo, clang 3.5 compiles fine
print_info<ProtectedFoo>("ProtectedFoo");
// g++ 5.2.1 fails to compile, clang 3.5 compiles fine
print_info<PrivateFoo>("PrivateFoo");
// both g++ 5.2.1 and clang 3.5 compile
print_info<NoFoo>("NoFoo");
return 0;
}
Why do I want to do this?
Skip this if you don't want to know the details. I just wrote this in case you were either shocked by the idea of me trying to detect protected members and/or curious about why I asked this question.
I was writing some kind of iterator template classes built out of other iterators and I got tired of writing multiple specializations depending on whether these iterators meet some requirements (ForwardIterator, BidirectionalIterator, RandomAccessIterator... although my iterators actually meet some relaxed versions of these concepts, they are kind of "proxy iterators" but it's not really relevant here).
For instance, if I only use random access iterators, my new custom iterator could (and should) also be some kind of random access iterator, hence implement operator+=, operator+, operator-=, operator-, operator<, operator>, operator<= and operator>=. However, some of these operators can easily be deduced from others, and they should only be defined if all the iterator I use are random access iterators.
I finally thought I'd just make something to provide default implementations if available. However, I wasn't really fond of the std::allocator_traits way as it wouldn't be very handy and readable with iterators (plus, I wouldn't be able to use them with some standard utilities).
The design I finally choose consists in having a template class which will build a full-fledged iterator out of a minimal implementation (for instance containing only the operator+=, operator==, operator* and operator> definitions) by having an inheritance chain of "mixins" (whose ancestor is my minimal iterator) detecting whether the functions/methods they need are available in their base class and defining the default methods if they are.
There is a subtility though. Sometimes I want to return a reference to the final iterator (for instance in Iterator& operator++()). If it's a method I redefine, I can easily solve that with CRTP and a static_cast, but what if my mixins don't touch that method at all?
I figured I should probably forbid the use of any method I haven't touched and inherit my minimal iterator with the protected access specifier... but now then my traits fail to detect the availability of some protected methods.
Therefore, I'd like to have traits able to detect whether some members are available with either public or protected visibility.

Use decltype on inherited template static member function using GCC

I have the below working code available on coliru.stacked-crooked.com.
As static std::false_type check(...) is duplicated, I wonder if we could factorize it. For instance within a base class. As pointed out by Jonathan Wakely my attempt at the bottom of my question compiles using Clang, but not using GCC.
I have tried many possibilities but it seems impossible to use decltype on inherited template static function using GCC.
Questions:
1. Is GCC-4.9 compliant with C++11 standard on this point?
2. What is the GCC-compliant workaround to use decltype on inherited template static member function?
#include <type_traits>
#include <iostream>
#include <string>
template<typename T>
struct is_addable
{
template<typename U> static std::false_type check(...);
template<typename U> static auto check(int)
-> decltype( std::declval<U>() + std::declval<U>(), std::true_type{});
using type = decltype(check<T>(0));
};
template<typename T>
struct is_multiplicable
{
template<typename U> static std::false_type check(...);
template<typename U> static auto check(int)
-> decltype( std::declval<U>() * std::declval<U>(), std::true_type{});
using type = decltype(check<T>(0));
};
int main()
{
std::cout <<"is_addable\n";
std::cout <<" long: "<< is_addable<long>::type::value <<'\n';
std::cout <<" string: "<< is_addable<std::string>::type::value <<'\n';
std::cout <<" void: "<< is_addable<void>::type::value <<'\n';
std::cout <<"is_multiplicable\n";
std::cout <<" long: "<< is_multiplicable<long>::type::value <<'\n';
std::cout <<" string: "<< is_multiplicable<std::string>::type::value <<'\n';
std::cout <<" void: "<< is_multiplicable<void>::type::value <<'\n';
}
One of my attempts
Edit: added template<typename U> as pointed out by Jonathan Wakely
struct default_check
{
template<typename U>
static std::false_type check(...);
};
template<typename T>
struct is_addable : default_check
{
using default_check::check;
template<typename U> static auto check(int)
-> decltype( std::declval<U>() + std::declval<U>(), std::true_type{});
using type = decltype(check<T>(0));
};
GCC-4.9.2 fails on coliru.stacked-crooked.com
> g++ -std=c++11 -Wall -pedantic -Wextra -Wfatal-errors main.cpp
main.cpp: In instantiation of 'struct is_addable<void>':
main.cpp:38:63: required from here
main.cpp:19:30: error: no matching function for call to 'is_addable<void>::check(int)'
using type = decltype(check<T>(0));
^
compilation terminated due to -Wfatal-errors.
Clang-3.4.1 succeeds on godbolt.org
> clang++ -std=c++11 -Wall -pedantic -Wextra -Wfatal-errors
Your default_check::check is not a template, so you can't call it like check<T>(0)
The solution is simply to make it a function template:
struct default_check
{
template<typename T> // <-- ADD THIS LINE
static std::false_type check(...);
};
Clang accepts that, but GCC still won't compile that (not sure why) so I'd just give up on default_check and write check everywhere you need it, as you had originally. It's clearer anyway.
I was going to suggest simplifying your syntax by defaulting the type parameter of the check function template in the derived classes:
template<typename T>
struct is_addable : default_check
{
using default_check::check;
template<typename U = T> static auto check(int)
-> decltype(std::declval<U>() + std::declval<U>(), std::true_type{});
using type = decltype(check(0));
};
but clang and gcc disagree on how to resolve the overload set. GCC apparently doesn't believe that the non-template check inherited from default_check is viable.
In any case, especially if you're going to have several of these traits, it would seem simpler to factor out "SFINAE check of a binary operation" into a template:
template<class...>
struct voider { using type = void; };
template<class...Ts>
using void_t = typename voider<Ts...>::type;
template <class T, class U, class BinaryOperation, class Enable = void>
struct is_binop_able_ : std::false_type {};
template <class T, class U, class BinOp>
struct is_binop_able_<T, U, BinOp, void_t<
decltype(std::declval<BinOp>()(
std::declval<T>(), std::declval<U>()))>> :
std::true_type {};
template <class T, class U, class BinOp>
using is_binop_able = typename is_binop_able_<T,U,BinOp>::type;
and create an alias for each of the desired traits that instantiates
that template with a generic function object type that implements the desired operation:
#define RETURNS(...) \
noexcept(noexcept(__VA_ARGS__)) \
->decltype(__VA_ARGS__) { \
return (__VA_ARGS__); \
}
struct plus {
template <class T, class U>
auto operator()(T t, U u) RETURNS(t + u)
};
template<class T, class U = T>
using is_addable = is_binop_able<T, U, plus>;
struct multiplies {
template <class T, class U>
auto operator()(T t, U u) RETURNS(t * u)
};
template<class T, class U = T>
using is_multiplicable = is_binop_able<T, U, multiplies>;
It's slightly less code per trait template, and you get handy reusable generic binary function object types as a nice side effect. The other nice side effect is that both GCC and clang compile it correctly: DEMO.
As #0x499602D2 states in a comment, the void specializations of the C++14 standard library function objects are almost exactly identical to the generic binary function objects implemented herein. If your library has C++14 implementations of them you could simply use them instead of writing your own (DEMO with GCC only, clang up to 3.6 blows up on is_multiplicable<std::string>, although clang trunk compiles it correctly):
template<class T, class U = T>
using is_addable = is_binop_able<T, U, std::plus<>>;
template<class T, class U = T>
using is_multiplicable = is_binop_able<T, U, std::multiplies<>>;

Resources