forcing template type to be reference by deduction

岁酱吖の 提交于 2020-06-29 06:54:10

问题


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 to T 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!