简体   繁体   English

std :: enable_if不编译(无效的模板参数)

[英]std::enable_if not compiling (invalid template argument)

I'm writing some code that should accept an std::unique_ptr and activate operator>> on its contents, filling the pointer if it is empty. 我正在编写一些应接受std :: unique_ptr并在其内容上激活operator >>的代码,如果该指针为空,则填充该指针。

I'm trying to limit unwanted calls by using SFINAE but I'm getting a bunch of error messages about template arguments being bad. 我试图通过使用SFINAE来限制不必要的调用,但是我收到了一堆关于模板参数错误的错误消息。

The code: 编码:

#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;
}

The errors: 错误:

// 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 ) );
               ^
  • What is wrong with the code here? 这里的代码有什么问题?
  • Is there a cleaner way of writing this? 有没有更干净的方式写这个? (Aside from the obvious "using std::unique_ptr" and such.) (除了明显的“ using std :: unique_ptr”之类的东西。)

"enable_if_t" doesn't work. “ enable_if_t”不起作用。 But I think it's just an extension of what I did wrong to make even enable_if not work in the first place. 但是我认为这只是我做错了什么的扩展,甚至使enable_if最初都不起作用。

I can tell something is very wrong because I also get an error message about operator* being applied to an int... which shouldn't have slipped inside at all (had SFINAE been implemented correctly)! 我可以说是很不对劲,因为我还收到一条关于将operator *应用于int的错误消息……这根本不应该放进内部(如果SFINAE正确实现)!

Another interesting issue here is the fact that the compiler doesn't recognize Serializable even though it's included just above it... If the answer is not trivial I'll look it up separately. 这里的另一个有趣的问题是,即使编译器位于其上方,编译器也无法识别Serializable。如果答案不重要,我将单独对其进行查找。

I'm compiling using MinGW 4.9.2 x32 on QtCreator 3.4.2 / Qt 5.5.0. 我正在QtCreator 3.4.2 / Qt 5.5.0上使用MinGW 4.9.2 x32进行编译。

Thank you. 谢谢。

EDIT: Please do not suggest to just create a function like this: 编辑:请不要建议只创建一个像这样的函数:

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

I must know the actual type of the object sent to this function and can't rely on polymorphism. 我必须知道发送给此函数的对象的实际类型,并且不能依赖多态性。

remove the typename before std::is_base_of<Serializable, T>::value (because std:is_base_of<...>::value is not a type) and move the enable_if part out of the parameter type (otherwise T will not be deducible). 移除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 )

The best way and the less intrusive one to do SFINAE is to use a non type template parameter: 进行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)
{
    // ...
}

And if you want to make it shorter: 如果要缩短它:

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)
{
    // ...
}

It should be way less intrusive and cause less problem with type deduction. 它应该减少干扰,并减少类型推导的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM