我想检查具有给定签名的函数是否存在。不同之处在于签名是由元组给定的:
#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
的嵌套调用。有没有解决此问题的方法?
答案 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在那里可以正常工作。