问题
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_cast
ing 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 toT
prior 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