现代C++技术研究(2)---模板类型推导(2)

第二种情况:ParamType是一个通用引用(Universal Reference)

这种情况,模板类型推导的结果,就不那么直观了。看如下测试用例:

#include 
#include 

template void f(T&& param)
{
    using ParamType = T&&;
    bool TIsInt = std::is_same::value;
    bool TIsConstInt = std::is_same::value;
    bool TIsIntRef = std::is_same::value;
    bool TIsConstIntRef = std::is_same::value;
    if (TIsInt) {
        std::cout << "T is int, ";
    } else if (TIsConstInt) {
        std::cout << "T is const int, ";
    } else if (TIsIntRef) {
        std::cout << "T is int&, ";
    } else if (TIsConstIntRef) {
        std::cout << "T is const int&, ";
    } 
    bool ParamTypeIsIntRef = std::is_same::value;
    bool ParamTypeIsConstIntRef = std::is_same::value;
    bool ParamTypeIsIntRefRef = std::is_same::value;
    if (ParamTypeIsIntRef) {
        std::cout << "param's type is int&\n";
    } else if (ParamTypeIsConstIntRef) {
        std::cout << "param's type is const int&\n";
    } else if (ParamTypeIsIntRefRef) {
        std::cout << "param's type is int&&\n";
    }
}

int main()
{
    int x = 27; // x is an int
    const int cx = x; // cx is a const int
    const int& rx = x; // rx is a reference to x as a const int
    f(x);  // x is lvalue, so T is int&, param's type is int&
    f(cx); // cx is lvalue, so T is const int&, param's type is const int&
    f(rx); // rx is lvalue, so T is const int&, param's type is const int&
    f(27); // 27 is rvalue, so T is int, param's type is int&&
    return 0;
}

可以看到,对于左值,T和ParamType类型相同,对于右值,T去引用,而ParamType是右值引用。

第三种情况:ParamType既不是指针也不是引用

1)传入的参数是引用情况:

#include 
#include 

template void f(T param)
{
    using ParamType = T;
    bool TIsInt = std::is_same::value;
    bool TIsConstInt = std::is_same::value;
    if (TIsInt) {
        std::cout << "T is int, ";
    } else if (TIsConstInt) {
        std::cout << "T is const int, ";
    }
    bool ParamTypeIsInt = std::is_same::value;
    bool ParamTypeIsConstInt = std::is_same::value;
    if (ParamTypeIsInt) {
        std::cout << "param's type is int\n";
    } else if (ParamTypeIsConstInt) {
        std::cout << "param's type is const int\n";
    }
}

int main()
{
    int x = 27; // x is an int
    const int cx = x; // cx is a const int
    const int& rx = x; // rx is a reference to x as a const int
    f(x); // T is int, param's type is int
    f(cx); // T is int, param's type is int
    f(rx); // T is int, param's type is int
    return 0;
}

可以看到,推导出的类型,T和ParamType是相同的,并且const和引用都被去掉了。

2)传入的参数是指针的情况:

#include 
#include 

using PtrType = const char* const;

template void f(T param)
{
    using ParamType = T;
    bool TIsCstCharPoint = std::is_same::value;
    bool TIsCstCharPointCst = std::is_same::value;
    if (TIsCstCharPoint) {
        std::cout << "T is const char*, ";
    } else if (TIsCstCharPointCst) {
        std::cout << "T is const char* const, ";
    }
    bool ParamTypeIsCstCharPoint = std::is_same::value;
    bool ParamTypeIsCstCharPointCst = std::is_same::value;
    if (ParamTypeIsCstCharPoint) {
        std::cout << "param's type is const char*\n";
    } else if (ParamTypeIsCstCharPointCst) {
        std::cout << "param's type is const char* const\n";
    }
}

int main()
{
    const char* const ptr = "Fun with pointers"; // ptr is const pointer to const object
    f(ptr); // T is const char*, param's type is const char*
    return 0;
}

可以看到,推导出的类型,T和ParamType是相同的,并且后面的const被去掉了,注意,前面的const属性是不能去掉的。

小结:

1)当ParamType是一个通用引用时,传入左值参数,模板的类型推导ParamType结果是左值引用,且ParamType和T相同,传入右值参数,模板的类型推导ParamType结果是右值引用,但ParamType和T是不同的,T去掉引用。

2)当模板参数是值传递时,const和volatile等修饰都会被去掉,且ParamType和T相同。

参考资料:

《Effective Mordern C++》

你可能感兴趣的:(C/C++技术,c++,开发语言)