是否存在Sfinae技术来检查几个声明?

发布于 2025-01-25 17:56:14 字数 1187 浏览 1 评论 0原文

在C ++ 17中,我想在使用SFINAE调用一些功能之前检查一些先决条件,例如:

class TestClass
{
public:
    bool foo() const { return true; }
    bool bar() { return false; }
};

template<typename T>
class Checker
{
public:
    template<typename Fn, typename = std::enable_if_t<(std::is_same_v<invoke_result_t<Fn, const T&>, bool>
                                                        || std::is_same_v<invoke_result_t<Fn>, bool>)>>
    void checkBoolConstFn(Fn fn) {}
};


int main()
{
    auto foo = [](const TestClass&) { return true; };
    auto bar = []() { return true; };

    Checker<TestClass> checker;
    checker.checkBoolConstFn(foo);
    checker.checkBoolConstFn(bar);
    checker.checkBoolConstFn(&TestClass::foo);
    checker.checkBoolConstFn(&TestClass::bar);

    return 0;
}

我尝试进行检查:如果fn的返回类型是bool,如果fn是接受一个参数还是零参数?

此代码不会编译,因为示例中的enabled_if_t中发生的替换失败,但是如果至少一个语句,我想以某种方式调用checkboolconstfn:

std::is_same_v<invoke_result_t<Fn, const T&>, bool>

std::is_same_v<invoke_result_t<Fn>, bool>

已编译。是否存在某种技术如何做?

In C++17, I want to check some prerequisite before invoke some function using SFINAE, example:

class TestClass
{
public:
    bool foo() const { return true; }
    bool bar() { return false; }
};

template<typename T>
class Checker
{
public:
    template<typename Fn, typename = std::enable_if_t<(std::is_same_v<invoke_result_t<Fn, const T&>, bool>
                                                        || std::is_same_v<invoke_result_t<Fn>, bool>)>>
    void checkBoolConstFn(Fn fn) {}
};


int main()
{
    auto foo = [](const TestClass&) { return true; };
    auto bar = []() { return true; };

    Checker<TestClass> checker;
    checker.checkBoolConstFn(foo);
    checker.checkBoolConstFn(bar);
    checker.checkBoolConstFn(&TestClass::foo);
    checker.checkBoolConstFn(&TestClass::bar);

    return 0;
}

i try to do check: is return type of Fn is bool if Fn is accept one argument OR zero argument?

This code doesn't compile because happens substitution failure in enabled_if_t in example, but i want to somehow invoke checkBoolConstFn if at least one of statement:

std::is_same_v<invoke_result_t<Fn, const T&>, bool>

or

std::is_same_v<invoke_result_t<Fn>, bool>

is compile. Is exists some technique how to do it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

坐在坟头思考人生 2025-02-01 17:56:14

似乎您需要的是 is_invocable_r_v ,即,我们只能确定fn是否可以用零参数调用或一个类型的参数const t&amp;产生可转换为bool

template<typename T>
class Checker
{
public:
    template<typename Fn, 
             typename = std::enable_if_t<
               (std::is_invocable_r_v<bool, Fn, const T&> || 
                std::is_invocable_r_v<bool, Fn>)>>
    void checkBoolConstFn(Fn fn) {}
};

demo

It seems like what you need is is_invocable_r_v, i.e., we can just determine whether Fn can be invoked with the zero argument or one argument of type const T& to yield a result that is convertible to bool

template<typename T>
class Checker
{
public:
    template<typename Fn, 
             typename = std::enable_if_t<
               (std::is_invocable_r_v<bool, Fn, const T&> || 
                std::is_invocable_r_v<bool, Fn>)>>
    void checkBoolConstFn(Fn fn) {}
};

Demo

梦旅人picnic 2025-02-01 17:56:14

也许是这样的:

template<typename T>
class Checker
{
public:
  template <typename Fn, typename = void>
  struct InvocableWithT : public std::false_type {};
  template <typename Fn>
  struct InvocableWithT<
    Fn,
    std::enable_if_t<std::is_same_v<std::invoke_result_t<Fn, const T&>, bool>>> 
  : public std::true_type {};

  template <typename Fn, typename = void>
  struct InvocableWithNone : public std::false_type {};
  template <typename Fn>
  struct InvocableWithNone<
    Fn,
    std::enable_if_t<std::is_same_v<std::invoke_result_t<Fn>, bool>>>
  : public std::true_type {};

    template<
      typename Fn,
      typename = std::enable_if_t<
        std::disjunction_v<InvocableWithT<Fn>, InvocableWithNone<Fn>>>>
    void checkBoolConstFn(Fn fn) {}
};

demo

Something like this, perhaps:

template<typename T>
class Checker
{
public:
  template <typename Fn, typename = void>
  struct InvocableWithT : public std::false_type {};
  template <typename Fn>
  struct InvocableWithT<
    Fn,
    std::enable_if_t<std::is_same_v<std::invoke_result_t<Fn, const T&>, bool>>> 
  : public std::true_type {};

  template <typename Fn, typename = void>
  struct InvocableWithNone : public std::false_type {};
  template <typename Fn>
  struct InvocableWithNone<
    Fn,
    std::enable_if_t<std::is_same_v<std::invoke_result_t<Fn>, bool>>>
  : public std::true_type {};

    template<
      typename Fn,
      typename = std::enable_if_t<
        std::disjunction_v<InvocableWithT<Fn>, InvocableWithNone<Fn>>>>
    void checkBoolConstFn(Fn fn) {}
};

Demo

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文