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

时间:2019-08-06 08:06:53

标签: c++ c++14 boost-hana

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

#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返回一个编译错误,而不是按照预期的方式处理。我了解这是由间接引起的-它仅验证对hana::unpack的调用(可以),而不验证对Lib::foo的嵌套调用。有没有解决此问题的方法?

1 个答案:

答案 0 :(得分:1)

当您在函数模板定义中引用的不是{em>立即模板扩展上下文的Lib::x时,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的尾随返回类型是立即模板扩展上下文,SFINAE在那里可以正常工作。