繁体   English   中英

SFINAE 用户定义转换算子

[英]SFINAE User-Defined-Conversion Operator

我正在尝试使用自省设计的模板化用户定义转换。

在 C++20 中,我可以执行以下操作:

    template<typename T>
    operator T() const
    {
        if constexpr( requires { PFMeta<T>::from_cursor(*this); } )
        {
            return PFMeta<T>::from_cursor(*this);
        }
        else
        {
            T x;
            std::memcpy(&x, &data, sizeof(x));
            return x;
        }
    }

即,如果PFMeta<T>::from_cursor(const struct PFCursor&)则使用它,否则执行 memcpy。 (godbolt 中的更长示例: https://godbolt.org/z/abed1vsK3

我喜欢这种方法,但不幸的是,这个库也需要在 C++17 上工作。

所以我一直在尝试将 SFINAE 作为概念的替代方案,但这非常棘手。 我终于设法得到类似的东西,但使用模板化方法as不是用户定义的转换运算符本身:

template<typename T, typename = void>
struct has_from_cursor : std::false_type { };

template<typename T>
struct has_from_cursor<T, decltype( PFMeta<T>::from_cursor(std::declval<struct PFCursor>()), void() ) > : std::true_type { };

// ...

    template<class T>
    std::enable_if_t<has_from_cursor<T>::value, T> as() const
    {
        return PFMeta<T>::from_cursor(*this);
    }

    template<class T>
    std::enable_if_t<!has_from_cursor<T>::value, T> as() const
    {
        T x;
        std::memcpy(&x, &data, sizeof(x));
        return x;
    }

我尝试了以下编译但不起作用的方法(我无法使用它):

    template<typename T>
    operator std::enable_if_t<has_from_cursor<T>::value, T>() const
    {
        return PFMeta<T>::from_cursor(*this);
    }

    template<typename T>
    operator std::enable_if_t<!has_from_cursor<T>::value, T>() const
    {
        T x;
        std::memcpy(&x, &data, sizeof(x));
        return x;
    }

更长的例子: https://godbolt.org/z/5r9Mbo18h

所以两个问题:

  • 对于用户定义的转换运算符,我可以有效地使用 C++17 中的 SFINAE 来有效地处理概念吗?
  • 有没有比类型特征和enable_if更简单的方法来执行as方法? 理想情况下,我想做一些事情,比如定义默认的模板化方法,然后在条件存在时有一个首选的专业化(即有一个元 class 和一个 static 成员 ZC1C425268E68385D1AB5074C17A 定义)

谢谢!

对于用户定义的转换运算符,我可以有效地使用 C++17 中的 SFINAE 来有效地处理概念吗?

if constepr考虑 C++17 支持。 鉴于您已经开发了从std::true_typestd::false_type false_type 继承的has_from_cursor自定义类型特征,您可以将它用于if constexp

我的意思是(注意:代码未经测试)

template<typename T>
operator T() const
{ // .............VVVVVVVVVVVVVVVVVVVVVVVVV
    if constexpr( has_from_cursos<T>::value )
    {
        return PFMeta<T>::from_cursor(*this);
    }
    else
    {
        T x;
        std::memcpy(&x, &data, sizeof(x));
        return x;
    }
}

有没有比类型特征和 enable_if 更简单的方法来执行 as 方法? 理想情况下,我想做一些事情,比如定义默认的模板化方法,然后在条件存在时有一个首选的专业化(即有一个元 class 和一个 static 成员 ZC1C425268E68385D1AB5074C17A 定义)

我想你可以尝试标签调度......

我的意思是从operator T()中调用 'as()' 并带有一个额外的int参数

template<typename T>
operator T() const
{ return as<T>(0); } // <-- call as() with a int

其中有一个特定于from_cursos class 的as() ,它接收未使用的int并且只是通过decltype()启用/禁用 SFINAE

template <typename T>  // ........accept an int; best match
decltype(PFMeta<T>::from_cursor(*this)) as (int) const
 { return PFMeta<T>::from_cursor(*this); }

和一个通用as() ,接收很long

template <typename T>
T as (long) const // <-- accept a long; worst match
 {
   T x;
   std::memcpy(&x, &data, sizeof(x));
   return x;
 }

诀窍是未使用的参数:一个int

当启用专用as()时,如果首选,因为接受int所以是更好的匹配。

当专用as()被禁用时,将通用as()保持为比没有更好的匹配。

暂无
暂无

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

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