强制模板类型通过演绎来引用

时间:2015-08-04 09:01:26

标签: c++ templates c++14

说我有一个函数func

template<typename T>
auto func(T arg){
    std::cout << std::boolalpha;
    std::cout << "T is ref: " << std::is_reference<T>::value << '\n';
}

有没有办法在不明确指定模板参数的情况下强制推导T作为参考类型?

喜欢能够写出类似的东西:

auto main() -> int{
    auto x = 5;
    func(std::ref(x));
}

但无需专攻std::reference_wrapper

static_cast不会阻止int& int的{​​{1}}衰减。

想象一下,我无法更改功能签名。

3 个答案:

答案 0 :(得分:4)

注意:这个anwer已被后期编辑声明无效,表明OP无法修改该功能。

类型演绎和参考折叠是您所需要的:

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);
}

输出:

T is ref: false
T is ref: true
T is ref: true

答案 1 :(得分:1)

  

想象一下,我无法更改功能签名。

签名

template<typename T>
auto func(T arg) { ... }

绝不会推断引用,因为类型推导适用于参数表达式的类型,而且来自[expr]:

  

如果表达式最初具有类型“T的引用”(8.3.2,8.5.3),则类型将在T之前调整为T   任何进一步的分析。

也就是说,只有在未明确提供模板参数的情况下才会发生模板推导。因此,您可以明确指定auto main() -> int{ auto x = 5; func<int&>(x); // T = int& }

template <typename T>
auto func_helper(T&& arg) {
    return func<T>(std::forward<T>(arg));
               ↑↑↑
}

否则,您可以在两者之间添加一个中间步骤:

func_helper

因为,在[temp.deduct.call]中:

  

如果P是转发引用且参数是a   左值,类型“左值引用A”用于代替A进行类型扣除。

因此,如果使用左值调用func_helper(x); ,模板参数P将被推导为参考。在您的示例中:

T

int&将被推断为func<int&>,因此我们明确调用与之前相同的函数:func_helper(5);

T

int将被推断为func<int>,我们会调用func,就像我们直接调用Capybara.current_driver = :selenium Capybara.app_host = 'http://www.google.com' ... visit('/')时一样。

答案 2 :(得分:0)

#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;
}

预期产出(原文如此):

T if ref: true
T if ref: true