2015-09-23 2 views
1

Я хотел создать псевдоним _t для std::is_base_of, аналогично тому, как std::enable_if_t является псевдонимом для std::enable_if. Поэтому я добавил следующее к моему стандартному заголовку:Написание пользовательских псевдонимов типа C++ 14 типа

namespace std { 
    template<typename T, typename U> 
    using is_base_of_t = typename is_base_of<T,U>::type; 
} 

Я использую этот новый псевдоним в следующем контексте:

template <typename SpaceT, 
      typename TagT, 
      typename = std::enable_if_t<std::is_base_of_t<Space,SpaceT>>> 
class SpatialTree : public SpaceT { 
}; 

И я получаю следующее сообщение об ошибке: Gcc

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>>> 

Что я делаю неправильно?

+0

вы должны поставить это в другом пространстве имен, например, 'xstd' и перейти на' std', когда это станет стандартизированным – TemplateRex

ответ

5

std::enable_if определяется таким образом:

template< bool B, class T = void > 
struct enable_if; 

Первый аргумент является значение, а не тип. В качестве первого аргумента необходимо передать std::is_base_of<Space,SpaceT>::value. С C++ 14, правильный псевдоним будет переменной шаблона:

template <class Base, class Derived> 
constexpr bool is_base_of_v = std::is_base_of<Base, Derived>::value; 

, что вы будете использовать один и тот же путь:

template <typename SpaceT, typename TagT, 
      typename = std::enable_if_t<is_base_of_v<Space,SpaceT>>> 
               ^^^ 
class SpatialTree : public SpaceT { 
}; 

Последнее в настоящее время существует в <experimental/type_traits>.

3

enable_if[_t] хочет в качестве первого аргумента bool. Вы должны написать std::enable_if_t<std::is_base_of_t<Space,SpaceT>::value> или std::enable_if_t<std::is_base_of_t<Space,SpaceT>{}>, иначе вы передадите тип, где требуется bool.

Однако, вы можете определить аналог std::experimental::is_base_of_v вместо:

template <class Base, class Derived> 
constexpr bool is_base_of_v = std::is_base_of<Base, Derived>{}; 

и использовать в качестве std::enable_if_t<is_base_of_v<Space, SpaceT>>.

Сказанное, я бы не определил ни один из этих шаблонов в пространстве имен std, так как это вызывает UB согласно [namespace.std]/1.

2

Доступно уже от Clang 3.6 и г ++ 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>, ""); 
} 
Смежные вопросы