有没有办法模板化一个函数,以便它可以接受通用情况下的T,或者如果模板参数解析为可调用的东西,可以接受专门化,例如仿函数,函数指针或{{1 }}?
例如,我想要这样的东西:
def login(email: String, password: String): Future[Option[User]] = {
import scala.concurrent.ExecutionContext.Implicits.global
repo.findBy("email", email)
.map { userOpt => userOpt.filter(user => BCrypt.checkpw(password, user.password)) }
}
答案 0 :(得分:1)
您无法部分专门化功能模板,因此您无法获得在问题中指明的语法。
你可以编写两个函数模板:一个用于T
可调用而没有参数,另一个用于何时不用。然后,您可以使用expression SFINAE禁用功能版本,并添加一个额外的函数参数,以使重载决策更适合该版本的可用版本:
template<typename T>
void use_this(T obj, float) {
obj->do_stuff();
}
template<typename Func>
auto use_this (Func func, int) -> decltype(func(), void()) {
use_this(func());
}
然后你可以添加一个包装器来提供消除歧义的参数:
template <typename T>
void use_this(T&& t) {
use_this(std::forward<T>(t), 0);
}
答案 1 :(得分:0)
x
我们现在有一个特征班namespace details {
template<template<class...>class Z, class, class...Ts>
struct can_apply : std::false_type{};
template<template<class...>class Z, class...Ts>
struct can_apply<Z, std::void_t<Z<Ts...>>, Ts...> : std::true_type{};
}
template<template<class...>class Z, class...Ts>
using can_apply = details::can_apply<Z,void, Ts...>
template<class Sig>
using can_invoke = can_apply< std::result_of_t, Sig >;
。
你传递签名。如果签名是有效的呼叫则是真实的,否则就是假的。
can_invoke
我使用了一些C ++ 11,例如template<class T>
std::enable_if_t< !can_invoke<T()> >
use_this( T obj ) {
obj->do_stuff();
}
template<class T>
std::enable_if_t< can_invoke<T()> >
use_this( T func ) {
use_this( func() );
}
,enable_if_t
和void_t
。所有这些都很容易用C ++ 11编写,并且易于搜索。
在传递无效签名时result_of_t
的行为在C ++ 14中已更改。在C ++ 11中,它不一定是SFINAE友好的。我们可以在C ++ 11中用result_of
替换std::result_of_t
,如下所示:
invoke_result_r
现在这是SFINAE友好的。
template<class Sig, class=void>
struct invoke_result {};
template<class Sig>
using invoke_result = typename invoke_result<Sig>::type;
template<class F, class...Args>
struct invoke_result<F(Args...),
decltype( void( std::declval<F>()( std::declval<Args>()... ) ) )
> {
using type = decltype( std::declval<F>()( std::declval<Args>()... ) );
};
类似于C ++ 20的can_apply
,但更短,更直观。
请注意,在非C ++ 11编译器(如MSVC)中执行此操作是不切实际的。但是,您可以使用标签分派执行类似的操作。