【问题标题】:std::enable_if not compiling (invalid template argument)std::enable_if 未编译(模板参数无效)
【发布时间】:2016-01-25 19:38:38
【问题描述】:

我正在编写一些代码,应该接受 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 都不起作用。

我可以说有些地方很不对劲,因为我还收到一条关于 operator* 被应用于 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)...

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

【问题讨论】:

    标签: c++ enable-if


    【解决方案1】:

    删除std::is_base_of&lt;Serializable, T&gt;::value之前的typename(因为std:is_base_of&lt;...&gt;::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。不过,我认为将enable_if 放在模板参数中更为常见。
    • 没想到从 enable_if 返回 Archive& 把它放到参数列表之外...好东西!
    【解决方案2】:

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

    它应该更少干扰,并且减少类型推断的问题。

    【讨论】:

    • 哇...所以直接在模板列表中使用 enable_if 作为限制器是可能的,很高兴知道。甜蜜的缩短技术,谢谢:)
    猜你喜欢
    • 2012-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多