鉴于类型A,B,我关注的是确切的定义std::common_type<A,B>,忽略了std::common_type<A...>任意类型的可变参数A....所以让
using T = decltype(true ? std::declval<A>() : std::declval<B>());
using C = std::common_type<A,B>;
Run Code Online (Sandbox Code Playgroud)
现在,根据一些消息来源,我发现了以下关系(typename为简洁而省略):
cppreference.com: C::type = std::decay<T>::type
cplusplus.com: C::type = T
GCC 4.8.1 <type_traits>实施: C::type = std::decay<T>::type如果T有效,否则C不包含::type成员("SFINAE友好")
Clang 3.3 <type_traits>实施: C::type = std::remove_reference<T>::type
我找到"SFINAE友好"版本的GCC的一个小细节,而std::remove_reference和std::decay实际上仅在内置阵列和功能,加上CV-资格有所区别,这再次我不关心了.所以我的问题是
应该是decay<T>::type还是只是T?使用的理由是decay<T>::type什么?它只是关于表示结果,A() + B()例如算术表达式吗?
例如,尝试了一下,我发现在"正义T"定义的情况下,我们有
common_type<int&,int&> = int&
common_type<int&,long&> = long …Run Code Online (Sandbox Code Playgroud) 所以我最近了解了通用引用和引用折叠。
假设我有这样的 max 函数的两种不同实现。
template<class T>
T&& max(T&& a, T&& b)
{
return (a < b) ? b : a;
}
template<class T>
const T& max(const T& a, const T& b)
{
return (a < b) ? b : a;
}
Run Code Online (Sandbox Code Playgroud)
一种版本通过 const 引用获取参数,另一种版本通过通用引用获取参数。
让我困惑的是什么时候应该使用它们。主要使用 const 传递,以便您可以将临时变量绑定到它。
在 stl 中也有不同的用途。std::move 采用通用引用,而 std::max 采用 const ref。
什么情况下应该使用两者?
假设我想在返回时避免复制或在返回时保留引用。函数的 const 和非常量版本是否有意义?
我有以下代码:
#include <iostream>
template <typename T>
void f (T) { std::cout << "f(T)" << std::endl; }
template <typename T>
void f (bool) { std::cout << "f(bool)" << std::endl; }
int main ( )
{
f(true); // #1 prints f(T)
f<bool>(true); // #2 prints f(bool)
}
Run Code Online (Sandbox Code Playgroud)
该#1行称f(T),虽然#2行调用f(bool).
为什么会这样?选择重载模板函数的规则是什么?
UPDATE
我明白在第一次调用时,编译器T在尝试调用第二个函数时无法推断,因此选择第一个函数.
在第二个调用中,第二个函数被认为是更好的匹配gcc,而第一个函数是在VS2013下选择的.谁在这里做对了?顺便说一下,我仍然对这个过程的完整描述感兴趣.
写一般的最小函数,我想到了两个问题.代码适用于任何输入类型和不同的参数号:
namespace xyz
{
template <typename T1, typename T2>
auto min(const T1 &a, const T2 &b) -> decltype(a+b)
{
return a < b ? a : b;
}
template <typename T1, typename T2, typename ... Args>
auto min(const T1 &a, const T2 &b, Args ... args) -> decltype(a+b)
{
return min(min(a, b), args...);
}
}
int main()
{
cout << xyz::min(4, 5.8f, 3, 1.8, 3, 1.1, 9) << endl;
// ^ ^ ^
// | | |
// float double …Run Code Online (Sandbox Code Playgroud)