c++ - etiqueta - que es param
Cómo forzar a una función a aceptar solo un parámetro de referencia lvalue (3)
Y quiero asegurarme de que el parámetro de plantilla F && f solo acepte una referencia de valor no constante.
Entonces no deberías haber usado una referencia de reenvío. La idea general de reenviar es aceptar cualquier categoría de valor y conservarla para futuras llamadas. Entonces, la primera solución es no usar la técnica incorrecta aquí, y aceptar por una referencia de valor l:
template<typename T, typename F>
inline
auto do_with(T&& rvalue, F& f) {
// As before
}
Eso debería hacer que el compilador se queje bien si intentas pasar un valor en la función. Sin embargo, no impedirá que el compilador permita valores constantes ( F
se deducirá como const F1
). Si realmente desea evitar eso, puede agregar otra sobrecarga:
template<typename T, typename F>
inline
void do_with(T&& , F const& ) = delete;
El tipo de parámetro F const&
coincidirá mejor con los valores const (y rvalues también, por cierto), por lo que este será seleccionado en resolución de sobrecarga, e inmediatamente causará un error porque se elimina su definición. Los valores no constantes se enrutarán a la función que desee definir.
Aquí está mi situación:
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);
});
}
Quiero asegurarme de que el parámetro de la plantilla F&& f
solo acepte una referencia de valor no const
. ¿Cómo debo hacer cumplir esto?
Puede tomar f
por referencia de valor static_assert
y evitar valores no constantes con static_assert
y is_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");
…
}
Con la introducción de constraints en C ++ 20, podrá utilizar una cláusula de requires
lugar:
template<typename T, typename F>
inline
auto do_with(T&& rvalue, F& f) requires !std::is_const_v<F> {
…
}
para agregar otra solución
template<typename T, typename F>
inline
auto do_with(T&& rvalue, F&& f) {
static_assert(!std::is_const<typename std::remove_reference<F>::type>::value, "must be non-const");
static_assert(std::is_lvalue_reference<F>::value, "must be lvalue reference");
...
}
o con SFINAE
template<typename T, typename F, typename std::enable_if<!std::is_const<typename std::remove_reference<F>::type>::value && std::is_lvalue_reference<F>::value, int>::type = 0>
inline
auto do_with(T&& rvalue, F&& f) {
}