强制通过推导引用模板类型

Cof*_*ode 2 c++ templates language-lawyer 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';
}
Run Code Online (Sandbox Code Playgroud)

有没有一种方法可以强制T将其推导为引用类型,而无需显式指定模板参数?

就像能够写出这样的东西:

auto main() -> int{
    auto x = 5;
    func(std::ref(x));
}
Run Code Online (Sandbox Code Playgroud)

但不必专门从事std::reference_wrapper.

static_casting 并不能阻止 的衰变int&为intfor T。

想象一下我无法更改函数签名。

Bar*_*rry 5

\n

想象一下我无法更改函数签名。

\n
\n\n

签名

\n\n
template<typename T>\nauto func(T arg) { ... }\n
Run Code Online (Sandbox Code Playgroud)\n\n

永远不会推导出引用,因为类型推导适用于参数表达式的类型,并且来自 [expr]:

\n\n
\n

如果表达式最初的类型为 \xe2\x80\x9c(对T\xe2\x80\x9d(8.3.2、8.5.3)的引用),则在T任何进一步分析之前将类型调整为\n。

\n
\n\n

也就是说,只有在未显式提供模板参数的情况下才会发生模板推导。所以你可以明确指定T:

\n\n
auto main() -> int{\n    auto x = 5;\n    func<int&>(x); // T = int&\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n
template <typename T>\nauto func_helper(T&& arg) {\n    return func<T>(std::forward<T>(arg));\n               \xe2\x86\x91\xe2\x86\x91\xe2\x86\x91\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n
\n

如果 P 是转发引用并且参数是左值,则使用对 A\xe2\x80\x9d 的类型 \xe2\x80\x9clvalue 引用代替 A 进行类型推导。

\n
\n\n

因此,如果func_helper使用左值调用,模板参数 P 将被推导为参考。在你的例子中:

\n\n
func_helper(x);\n
Run Code Online (Sandbox Code Playgroud)\n\n

T将被推导为int&,因此我们显式调用与之前相同的函数:func<int&>。

\n\n
func_helper(5);\n
Run Code Online (Sandbox Code Playgroud)\n\n

T将被推导为int,并且我们将调用func<int>,与直接调用时发生的情况相同func。

\n