说我有一个函数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}}衰减。
想象一下,我无法更改功能签名。
答案 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