当元组给出参数时如何检查方法是否存在?

How to check if method exists when arguments are given by the tuple?

我想检查是否存在具有给定签名的函数。不同之处在于签名由元组给出:

#include <boost/hana/type.hpp>
#include <boost/hana/tuple.hpp>
#include <tuple>
namespace hana = boost::hana;

struct LibA {
   static int foo(int, float, double) { return 1;}
};

struct LibB {
   static int bar(float, float, float) { return 2;}
};

template<typename Lib, typename... Args>
int call(Lib, hana::tuple<Args...> args) {
   auto hasFoo = hana::is_valid(hana::unpack)(args, Lib::foo);
   auto hasBar = hana::is_valid(hana::unpack)(args, Lib::bar);

   static_assert(hana::if_(hasFoo || hasBar, true, false), "Cannot find both positional and named version of the functor.");
   return(hana::if_(hasFoo, 
          hana::unpack(args, Lib::foo),
          hana::unpack(args, Lib::bar)
   ));
}


int main() {
   int i; float f; double d;
   call(LibA(), hana::make_tuple(i, f, d)); //compile error: 'bar' is not a member of LibA
   call(LibB(), hana::make_tuple(f, f, f)); //compile error: 'foo' is not a member of libB
}

hana::is_valid returns 编译错误而不是按预期处理它。我知道这是由间接引起的——它只验证对 hana::unpack 的调用,这没问题,但不是对 Lib::foo 的嵌套调用。这个问题有解决方法吗?

当您在函数模板定义中引用 Lib::x 时,它不是 immediate 模板扩展上下文,因此 SFINAE 不适用于那里,因此您会得到一个编译器错误。

只有函数类型及其模板参数类型的直接上下文中的无效类型和表达式会导致推导失败。

另一种可行的解决方案:

struct LibA {
    static int foo(int, float, double) { return 1; }
};

struct LibB {
    static int bar(float, float, float) { return 2; }
};

template<typename Lib, typename... Args>
auto call(Lib, hana::tuple<Args...> args) -> decltype(hana::unpack(args, Lib::foo)) {
    return hana::unpack(args, Lib::foo);
}

template<typename Lib, typename... Args>
auto call(Lib, hana::tuple<Args...> args) -> decltype(hana::unpack(args, Lib::bar)) {
    return hana::unpack(args, Lib::bar);
}

int main() {
    int i; float f; double d;
    call(LibA(), hana::make_tuple(i, f, d));
    call(LibB(), hana::make_tuple(f, f, f));
}

在上面,带有 decltype 的尾随 return 类型是一个 立即 模板扩展上下文,SFINAE 在那里按预期工作。