std :: enable_if没有编译(模板参数无效)

时间:2016-01-25 19:38:38

标签: c++ enable-if

我正在编写一些应该接受std :: unique_ptr并激活运算符>>的代码。在其内容上,如果指针为空则填充指针。

我正试图通过使用SFINAE来限制不需要的调用,但是我收到一些关于模板参数错误的错误消息。

代码:

#include "serializable.h"

template <class Archive, typename T>
Archive &operator>>( Archive &in, std::unique_ptr<typename std::enable_if<typename std::is_base_of<Serializable, T>::value, T>::type> &ptr )
{
    if ( !ptr )
        ptr.swap( Serializable::construct_from_stream( in ) ); // Constructs a Serializable derivative.

    in >> *ptr;
    return in;
}

错误:

// 1
error: template argument 1 is invalid
 Archive &operator>>( Archive &in, std::unique_ptr<typename std::enable_if<typename std::is_base_of<Serializable, T>::value, T>::type> &ptr )
                                                                                                                                     ^
// 2
error: template argument 2 is invalid

// 3
error: expected '::' before '&' token
 Archive &operator>>( Archive &in, std::unique_ptr<typename std::enable_if<typename std::is_base_of<Serializable, T>::value, T>::type> &ptr )
                                                                                                                                       ^
// 4
error: expected identifier before '&' token

// 5
error: request for member 'swap' in 'ptr', which is of non-class type 'int'
         ptr.swap( Serializable::construct_from_stream( in ) );
             ^
// 6
error: type/value mismatch at argument 1 in template parameter list for 'template<bool <anonymous>, class _Tp> struct std::enable_if'
     std::unique_ptr<typename std::enable_if<typename std::is_base_of<Serializable, T>::value, Serializable>::type>
                                                                                                           ^
// 7
error: 'Serializable' has not been declared
     ptr.swap( Serializable::construct_from_stream( in ) );
               ^
  • 这里的代码有什么问题?
  • 有没有更清晰的写作方式? (除了显而易见的“使用std :: unique_ptr”等。)

“enable_if_t”不起作用。但我认为这只是我做错的一个扩展,即使enable_if首先也不起作用。

我可以告诉一些事情是非常错误的,因为我还得到一条关于运算符*应用于int的错误消息...根本不应该在内部滑动(已经正确实现了SFINAE)!

另一个有趣的问题是编译器无法识别Serializable,即使它包含在它上面......如果答案不是微不足道的话,我会单独查看。

我在QtCreator 3.4.2 / Qt 5.5.0上使用MinGW 4.9.2 x32进行编译。

谢谢。

编辑:请不要建议只创建这样的函数:

Archive &operator>>( Archive &in, std::unique_ptr<Serializable> &ptr)...

我必须知道发送给这个函数的对象的实际类型,并且不能依赖于多态。

2 个答案:

答案 0 :(得分:2)

typename之前移除std::is_base_of<Serializable, T>::value(因为std:is_base_of<...>::value不是类型)并将enable_if部分移出参数类型(否则T将不可扣除)。

template <class Archive, typename T>
typename std::enable_if<
    std::is_base_of<Serializable, T>::value,
    Archive &
>::type
  operator>>( Archive &in, std::unique_ptr<T> &ptr )

答案 1 :(得分:1)

使用非类型模板参数的最佳方式和较少侵入性的SFINAE:

template <class Archive, typename T,
    std::enable_if_t<std::is_base_of<Serializable, T>::value, int> = 0
>
Archive &operator>>( Archive &in, std::unique_ptr<T>& ptr)
{
    // ...
}

如果你想缩短它:

template<typename Cond>
using my_enable = std::enable_if_t<Cond::value, int>;

template<typename T>
using is_serializable = std::is_base_of<Serializable, T>;

template <class Archive, typename T, my_enable<is_serializable<T>> = 0>
Archive &operator>>( Archive &in, std::unique_ptr<T>& ptr)
{
    // ...
}

应该减少干扰,减少类型扣除的问题。