我已经编写了一个模板化函数,旨在接受lambda和一堆参数。我已将函数的返回类型声明为lambda的返回类型。有什么方法可以让我的模板化函数专门用于某些lambda参数返回类型?
我的代码的工作部分如下:
template <typename F, typename ... T>
auto crudeProfile(F f, T ... args) -> decltype(f(args...)) {...}
这就像我期望的那样工作。但我想将其行为专门针对返回无效值的lambda。到目前为止,我只想出了以下代码:
template <typename F, typename ... T>
void crudeProfile(F f, T ... args) {...}
但是当我尝试使用它时,编译器会抱怨这一点:
1>Source.cpp(684): error C2668: 'crudeProfile': ambiguous call to overloaded function
1> Source.cpp(637): note: could be 'void crudeProfile<main::<lambda_a7118596c99e3162db30942634c4e81e>,>(F)'
1> with
1> [
1> F=main::<lambda_a7118596c99e3162db30942634c4e81e>
1> ]
1> Source.cpp(624): note: or 'void crudeProfile<main::<lambda_a7118596c99e3162db30942634c4e81e>,>(F)'
1> with
1> [
1> F=main::<lambda_a7118596c99e3162db30942634c4e81e>
1> ]
1> Source.cpp(684): note: while trying to match the argument list '(main::<lambda_a7118596c99e3162db30942634c4e81e>)'
即使返回非空的lambda也会导致此错误,尽管该错误会稍有变化,显示为“可能是'type'或void”(其中'type'是lambda返回类型是什么)。
答案 0 :(得分:1)
有没有办法专门化我的模板化函数?
不,您不能,但是有一种解决方法。
对我来说升级到C ++ 17可能不会受伤...
因此在C ++ 17中,多亏了if constexpr
,您可以为此编写一个非常简单的解决方法,而又不会过多地损害您的代码,如下所示:
template <typename F, typename ... Ts>
decltype(auto) crudeProfile(F f, Ts ... args)
{
if constexpr (std::is_same_v<std::invoke_result_t<F, Ts...>, void>)
{
// void
}
else
{
// not void
}
}
答案 1 :(得分:0)
您不能部分专门化函数模板,并且重载也是不可能的事情 1 ,所以您必须诉诸于类。请注意,如果可以访问C ++ 17,则可以使用if constexpr
来简化很多操作。
template <typename F, typename = void, typename... Ts>
struct helper {
auto operator()(F f, Ts... args) -> decltype(f(args...)) {
// your code
}
};
template <typename F, typename... Ts>
struct helper<F, typename std::result_of<F(Ts...)>::type, Ts...> {
void operator()(F f, Ts... args) {
// specialization for void
}
};
template <typename F, typename... Ts>
auto crudeProfile(F f, Ts... args) -> decltype(f(args...)) {
return helper<F, Ts...>(f, args...);
}
注意:std::result_of
被std::invoke_result
取代,因此,如果您可以改用(C ++ 17),请改用它。
1 请注意,您仍然可以使用SFINAE,但是我不喜欢此选项,因为这将需要您复制一个二进制条件(即,调用f(args...)
的结果是一个空白)。
如果要这样做而不是通过帮助程序,只需在两个重载中添加一个附加模板参数即可:typename std::enable_if<!std::is_same<void, typename std::result_of<F(Ts...)>::type>::value>::type* = nullptr>
。不要忘记删除第二个过载的否定项。