C ++模板参数推导过程

时间:2012-11-07 08:34:22

标签: c++

任何人都可以帮忙告诉我为什么参数演绎不符合我的预期吗?请参阅我的代码评论我的思路?

#include <iostream>
#include <type_traits>
#include <iomanip>
#include <string>

using namespace std;

template<class T>
void deduce1(T args, string arg){
cout << "template<class T> void deduce1(T args) " << " argument passed in was: " << arg << " deduced as: " << typeid(T).name() << endl;
cout <<  "Is const: " << boolalpha << is_const<T>::value << endl;
cout <<  "Is reference: " << boolalpha << is_reference<T>::value << endl;
cout <<  "Is pointer: " << boolalpha << is_pointer<T>::value << endl;
}

template<class T>
void deduce2(T& args,string arg){
cout << "template<class T> void deduce2(T args) " << " argument passed in was: " << arg << " deduced as: " << typeid(T).name() << endl;
cout <<  "Is const: " << boolalpha << is_const<T>::value << endl;
cout <<  "Is reference: " << boolalpha << is_reference<T>::value << endl;
cout <<  "Is pointer: " << boolalpha << is_pointer<T>::value << endl;
}

template<class T>
void deduce3(T&& args,string arg){
cout << "template<class T> void deduce3(T args) " << " argument passed in was: " << arg << " deduced as: " << typeid(T).name() << endl;
cout <<  "Is const: " << boolalpha << is_const<T>::value << endl;
cout <<  "Is reference: " << boolalpha << is_reference<T>::value << endl;
cout <<  "Is rvalue reference: " << boolalpha << is_rvalue_reference<T>::value << endl;
cout <<  "Is pointer: " << boolalpha << is_pointer<T>::value << endl;
}

int _tmain(int argc, _TCHAR* argv[])
{

int a = 1;
const int b = 5;
int c[] = {12};
int const d[] = {12};
int& e = a;

deduce1(a,"int a = 1");
deduce1(b,"const int b = 5");
deduce1(c,"int c[] = {12}");
deduce1(d,"int const d[] = {12}"); // would have thought is_const<T> would return true any comments?
deduce1(e,"int& e = a");
deduce1(5,"5");

deduce2(a,"int a = 1");
deduce2(b,"const int b = 5"); //would have though type would be deduced as int const comments?
deduce2(c,"int c[] = {12}"); // why is this not returning true as a reference?
deduce2(d,"int const d[] = {12}"); // would have thought is_const<T> would return true any comments
deduce2(e,"int& e = a");

deduce3(a,"int a = 1");
deduce3(b,"const int b = 5");
deduce3(c,"int c[] = {12}"); // why is this not returning true as a reference?
deduce3(d,"int const d[] = {12}"); // would have thought is_const<T> would return true any comments
deduce3(e,"int& e = a");
deduce3(string("Hello"),"string(\"Hello\")"); // why not rvalue reference


return 0;
}

1 个答案:

答案 0 :(得分:0)

我将依次处理你的每一条评论。

  1. deduce1d

    template <class T> void deduce1(T args, string arg);
    int const d[] = {12};
    deduce1(d, "int const d[] = {12}"); // would have thought is_const<T> would return true
    

    第一个重要的是你不能通过C ++中的值传递数组作为参数。表示数组的表达式几乎会立即衰减到指向其第一个元素的指针。因此,此处T推导出的类型为int const *

    所以,为什么这不起作用?问题是指针不是const。指针指向的intconst。如果您要报告所指向类型的const,则在检查remove_pointer之前,您需要使用const。因此,您可以将const检查更改为:

    cout <<  "Is const: " << boolalpha << is_const<typename remove_pointer<T>::type>::value << endl;
    

    然而,之前给出的结果是正确答案。指针确实不是const。实际上,即使指针为const,顶级consts也会在类型扣除完成之前被删除,因此T无论如何都不会const。这样做的原因是,如果你通过值传递,你实际上并不关心参数的const,因为你无论如何都要复制它。

  2. deduce2b

    template <class T> void deduce2(T& args,string arg);
    const int b = 5;
    deduce2(b,"const int b = 5"); //would have though type would be deduced as int const
    

    不确定这里发生了什么,但我的输出是:

    deduced as: i
    Is const: true
    Is reference: false
    Is pointer: false
    

    完全符合预期。

  3. deduce2c

    int c[] = {12};
    deduce2(c,"int c[] = {12}"); // why is this not returning true as a reference?
    

    它说这不是一个引用,因为所有deduce2调用都说同样的原因(并且deduce3也存在这个问题)。在您的函数中,您正在检查T的类型,但args的类型为T&。您只是在&之前检查零件。所以,args的类型为int (&)[1] c,但您只是在检查int [1]是否为引用。在您的支票中使用decltype(args)代替T进行修复。

  4. deduce2d

    int const d[] = {12};
    deduce2(d,"int const d[] = {12}"); // would have thought is_const<T> would return true
    

    deduce1 d(第1项)相同的问题。

  5. deduce3c

    template <class T> void deduce3(T&& args,string arg);
    int c[] = {12};
    deduce3(c,"int c[] = {12}"); // why is this not returning true as a reference?
    

    deduce2c(第3项)相同的问题。

  6. deduce3d

    int const d[] = {12};
    deduce3(d,"int const d[] = {12}"); // would have thought is_const<T> would return true
    

    deduce1 d(第1项)相同的问题。

  7. deduce3string("Hello")

    deduce3(string("Hello"),"string(\"Hello\")"); // why not rvalue reference
    

    我假设您对“通用引用”有所了解。 Scott Meyers在这个问题上有一个很棒的articletalk

    在这种情况下,由于string("Hello")是一个右值表达式,因此T类型推导为string(由T&&形式的推导的右值引用类型的规则推导出来)。 args的类型现在为string &&。因此,如果你检查decltype(args)是否是左值,它会说是真的。但T本身并非如此。

  8. 如果您修复了代码,以便T上的所有类型特征现在都在decltype(args),那么您将遇到新问题。当args属于引用类型时,您希望为const的某些类型不会。那是因为没有const引用这样的东西。与在第1项中使用remove_pointer类似,您需要使用remove_reference来获取基础类型并检查它是否为const