【问题标题】:std::is_invocable<...> checking for member functionstd::is_invocable<...> 检查成员函数
【发布时间】:2020-04-16 21:37:53
【问题描述】:

以下代码正确确定何时可以为给定的T 调用Writer( t )

template <typename T>
inline void Process( const T& t )
{
    if constexpr ( std::is_invocable<decltype(Writer), const T&>::value )
    {
        Writer( t );
    }
    else { //... }
}

但我只能让它适用于 Writer 中定义的 operator(),例如

class Writer
{
 public:
    operator()( const int& )
    {
        \\...
    }
}

我如何对成员函数进行相同的检查,即检查该函数是否存在,例如对于Write(...) in

class Writer
{
public:
    inline void Write( const int& t )
    {
    }
};

class Archive
{

public:

    template <typename T>
    inline void Process( const T& t )
    {
        //check if Writer can handle T
        if constexpr ( std::is_invocable_v<decltype( ???&Writer::Write??? ), ???, const T&> )
        {
            TheWriter.Write( t );
            std::cout << "found";
        }
        else
        {    
            std::cout << "not found";
        }
    }

    Writer TheWriter;

};

我在if constexpr 中尝试的Writer.WriteWriter::Writedecltype&amp; 的每个可能组合都会导致编译器错误,甚至fatal error C1001

这是在带有 /std:c++17 的 Visual Studio 2017 MSVC_1916 上。

【问题讨论】:

  • Writer.Write( t ); 行也是错误的:. 的左侧必须是对象,而不是类的名称。该函数是否真的需要Writer 对象,或者是否可以在不存在任何Writer 对象的情况下调用它?
  • 模板上的inline 关键字毫无意义。模板已经具有与内联函数相同的语义(显式特化和实例化除外)。
  • 抱歉,缩短了太多。当然有会员Writer Writer编辑了这个。
  • 我认为微软把这些事情搞砸的日子已经一去不复返了......无论如何,最后,我选择了一个不同的——更好的重载+SFIN​​AE 解决方案。无论如何,这些检查都太脆弱了。

标签: c++ visual-c++ c++17 std


【解决方案1】:

您可以像这样检查成员函数:

template <typename T>
inline void Process( const T& t )
{
    if constexpr ( std::is_invocable_v<decltype(&Writer::Write), Writer&, T const &> )    
    {
        Writer{}.Write(t);
    }
    else 
    { 
        //... 
    }
}

这是一个有效的demo。感谢@aschepler 指出原始 sn-p 中的错误。

【讨论】:

  • 这是看起来合乎逻辑的变体,但会导致 fatal error C1001: An internal error has occurred in the compiler. 所以它可能是正确的。 ;-)
  • 我认为std::is_invocable_v&lt;decltype(&amp;Writer::Write), Writer&amp;, const T&amp;&gt;。指向非静态成员函数的指针需要一个对象来调用该函数,std::invoke 和朋友将此类类型/对象视为第一个参数/参数。
  • @DoctorNuu 我添加了 aschepler 的更正,以及一个工作示例的链接。
  • 我自己的玩具示例在有和没有Writer&amp; 的情况下都可以工作,请参阅godbolt.org/z/3ptza_ 但是完整的代码会产生致命错误。
  • @DoctorNuu 我修改了你的 sn-p slightly,它使用 gcc 失败(应该如此),但 MSVC 出现致命错误。也许是一个错误?
猜你喜欢
  • 1970-01-01
  • 2023-03-31
  • 1970-01-01
  • 1970-01-01
  • 2010-12-27
  • 2016-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多