如何强制函数仅接受左值引用参数

Lew*_*han 17 c++ templates

这是我的情况:

template<typename T, typename F>
inline
auto do_with(T&& rvalue, F&& f) {
    auto obj = std::make_unique<T>(std::forward<T>(rvalue));
    auto fut = f(*obj);
    return fut.then_wrapped([obj = std::move(obj)] (auto&& fut) {
        return std::move(fut);
    });
}
Run Code Online (Sandbox Code Playgroud)

我想确保模板参数F&& f只接受非const左值引用.我应该如何强制执行此操作?

Sto*_*ica 35

我想确保模板参数F && f只接受非const左值引用.

那你就不应该使用转发参考.转发的整个想法是接受任何值类别并保留它以供将来调用.所以第一个修复是不要在这里使用错误的技术,而是通过左值引用来接受:

template<typename T, typename F>
inline
auto do_with(T&& rvalue, F& f) {
  // As before
}
Run Code Online (Sandbox Code Playgroud)

如果你试图将rvalue传递给函数,这应该会让编译器很好地抱怨.它不会阻止编译器允许const左值(F将被推断为const F1).如果你真的想要阻止它,你可以添加另一个重载:

template<typename T, typename F>
inline
void do_with(T&& , F const& ) = delete;
Run Code Online (Sandbox Code Playgroud)

参数类型F const&将更好地匹配const lvalues(和rvalues,btw),因此这个将在重载决策中被选中,并立即导致错误,因为它的定义被删除.非常量左值将被路由到您要定义的函数.


Jos*_*son 12

您可以f通过左值引用和防止非常量值与static_assertis_const:

template<typename T, typename F>
inline
auto do_with(T&& rvalue, F& f) {
    static_assert(!std::is_const<F>::value, "F cannot be const");
    …
}
Run Code Online (Sandbox Code Playgroud)

通过在C++ 20中引入约束,您将能够使用一个requires子句:

template<typename T, typename F>
inline
auto do_with(T&& rvalue, F& f) requires !std::is_const_v<F> {
    …
}
Run Code Online (Sandbox Code Playgroud)