问题
Say I have a function func:
template<typename T>
auto func(T arg){
std::cout << std::boolalpha;
std::cout << "T is ref: " << std::is_reference<T>::value << '\n';
}
Is there a way I can force T to be deduced as a reference type without explicitly specifying the template parameters?
Like being able to write something like:
auto main() -> int{
auto x = 5;
func(std::ref(x));
}
but without having to specialize for std::reference_wrapper.
static_casting does not stop the decay of int& into int for T.
Imagine that I can not change the function signature.
回答1:
Imagine that I can not change the function signature.
The signature
template<typename T>
auto func(T arg) { ... }
will never deduce a reference because type deduction works on the type of the expression of the arguments, and from [expr]:
If an expression initially has the type “reference to
T” (8.3.2, 8.5.3), the type is adjusted toTprior to any further analysis.
That said, template deduction only happens if the template parameters are not explicitly provided. So you can explicitly specify T:
auto main() -> int{
auto x = 5;
func<int&>(x); // T = int&
}
Otherwise, you could add a middle step in between:
template <typename T>
auto func_helper(T&& arg) {
return func<T>(std::forward<T>(arg));
↑↑↑
}
Because, in [temp.deduct.call]:
If P is a forwarding reference and the argument is an lvalue, the type “lvalue reference to A” is used in place of A for type deduction.
So if func_helper is called with an lvalue, the template parameter P will be deduced as a reference. In your example:
func_helper(x);
T will be deduced as int&, so we explicitly call the same function as we did before: func<int&>.
func_helper(5);
T would be deduced as int, and we would call func<int>, the same as would have happened if we had called func directly.
回答2:
Note: this anwer has been invalidated by the late edit stating that OP could not modify the function.
Type deduction and reference collapsing are what you need :
template<class T>
auto func(T&&) {
std::cout << std::boolalpha << "T is ref: " << std::is_reference<T>::value << '\n';
}
int main() {
func(5);
int i = 7;
func(i);
int const j = 9;
func(j);
}
Output :
T is ref: false
T is ref: true
T is ref: true
回答3:
#include <iostream>
#include <type_traits>
#include <iomanip>
using namespace std;
template<typename T>
auto func(T arg)
{
std::cout << std::boolalpha;
std::cout << "T if ref: " << std::is_reference<decltype(arg)>::value << "\n";
}
template<class T>
auto func_wrapper(T& arg)
{
func<T&>(arg);
}
#define func func_wrapper
auto main() -> int
{
auto x = 5;
func(x);
auto& y = x;
func(y);
return 0;
}
expected output (sic):
T if ref: true
T if ref: true
来源:https://stackoverflow.com/questions/31804946/forcing-template-type-to-be-reference-by-deduction