Reputation: 7773
I wanted to create a _t
alias for std::is_base_of
, similar to how std::enable_if_t
is an alias for std::enable_if
. So I added the following to my standard header:
namespace std {
template<typename T, typename U>
using is_base_of_t = typename is_base_of<T,U>::type;
}
I'm using this new alias in the following context:
template <typename SpaceT,
typename TagT,
typename = std::enable_if_t<std::is_base_of_t<Space,SpaceT>>>
class SpatialTree : public SpaceT {
};
And I'm getting the following gcc error:
SpatialTree.h:48:101: error: type/value mismatch at argument 1 in template parameter list for ‘template<bool _Cond, class _Tp> using enable_if_t = typename std::enable_if::type’
template <typename SpaceT, typename TagT, typename = std::enable_if_t<std::is_base_of_t<Space,SpaceT>>>
What am I doing wrong?
Upvotes: 1
Views: 549
Reputation: 70526
Available already as of Clang 3.6 and g++ 5.1
#include <experimental/type_traits>
using namespace std::experimental;
struct B {}; struct D : B {};
int main()
{
static_assert(is_base_of_v<B, D>, "");
}
Upvotes: 2
Reputation: 302892
std::enable_if
is defined thusly:
template< bool B, class T = void >
struct enable_if;
The first argument is a value, not a type. You need to pass in std::is_base_of<Space,SpaceT>::value
as the first argument. With C++14, the correct alias would be a variable template:
template <class Base, class Derived>
constexpr bool is_base_of_v = std::is_base_of<Base, Derived>::value;
that you'd use the same way:
template <typename SpaceT, typename TagT,
typename = std::enable_if_t<is_base_of_v<Space,SpaceT>>>
^^^
class SpatialTree : public SpaceT {
};
The latter currently exists in <experimental/type_traits>
.
Upvotes: 5
Reputation: 60979
enable_if
[_t
] wants a bool
as its first argument. You have to write std::enable_if_t<std::is_base_of_t<Space,SpaceT>::value>
or std::enable_if_t<std::is_base_of_t<Space,SpaceT>{}>
, otherwise you pass a type where a bool
is required.
However, you might want to define a counterpart of std::experimental::is_base_of_v
instead:
template <class Base, class Derived>
constexpr bool is_base_of_v = std::is_base_of<Base, Derived>{};
and use as std::enable_if_t<is_base_of_v<Space, SpaceT>>
.
That said, I wouldn't define either of these templates in namespace std
, since that invokes UB as per [namespace.std]/1.
Upvotes: 3