有没有办法根据 lambda 参数返回类型部分专用化我的模板化函数?
Is there a way to partially specialize my templated function based on a lambda parameter return type?
我编写了一个模板化函数,旨在接受lambda和一包参数。我已经声明了函数的返回类型是 lambda 的返回类型。有没有办法将我的模板化函数专门用于某些 lambda 参数返回类型?
我的代码的工作部分如下:
template <typename F, typename ... T>
auto crudeProfile(F f, T ... args) -> decltype(f(args...)) {...}
这符合我的预期。但我想将其行为专门用于返回 void 的 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>)'
即使是返回非 void 的 lambda 也会导致此错误,尽管错误会略有变化,读作"可能是'类型'或 void"(其中 'type' 是 lambda 返回类型是什么(。
有没有办法部分地专门化我的模板化函数?
不,你不能,但有一个解决方法。
升级(到 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,所以你必须求助于类。请注意,如果您有权访问 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>
.不要忘记删除第二次重载的否定。
- 我的神经网络不起作用 [XOR 问题]
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 我的字符计数代码计算错误.为什么
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- cmake在我的项目中所需的所有静态库都不成功
- 为什么我的代码在输出中增加了93天
- 我的简单if-else语句是如何无法访问的代码
- 为什么我的for循环不能正确获取argv
- 我的项目不会像"undefined reference to `grpc::g_core_codegen_interface'"那样使用未定义的引用错误进行编译
- 0-1背包代码中的错误.我的代码中有什么错误
- 当我的阵列太大时出现分段错误
- 如何确认我的constexpr表达式实际上已经在编译时执行
- 有没有办法根据 lambda 参数返回类型部分专用化我的模板化函数?
- 我的C++模板失败:非模板结构的显式专用化
- 为什么我的专用模板函数'OverloadedFunk' C++中给出"could not be resolved"错误?
- 我如何将我的类模板部分专用化为int_<...>,long_<...>
- 当我尝试部分专用化函数模板时,为什么我的程序不起作用?
- 我的模板专用化与发布版本不同调试版本,是这个 gcc 错误
- 为什么我的专用模板函数只在调试构建中调用?
- 如果我的模板专用化没有被执行,为什么会被编译?