4

任何人都可以帮助告诉我为什么论点推论没有按我的预期工作吗?请查看我的代码注释以了解我的思路?

#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;
}
4

1 回答 1

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. 指针指向的ints 是const。如果要报告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但类型argsT&。您只检查&. 所以在这里,argsis的类型,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与(第 1 项)相同的问题d

  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?
    

    deduce2与(第 3 项)相同的问题c

  6. deduce3d

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

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

  7. deduce3string("Hello")

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

    我将假设您对“通用参考”有所了解。Scott Meyers 有一篇很棒的文章和关于这个主题的演讲。

    在这种情况下,因为string("Hello")是一个右值表达式,所以类型T被推导为string(通过推导右值引用类型的规则T&&)。的类型args是现在string &&。所以如果你检查是否decltype(args)是一个右值,它会说是真的。但T它本身不是。

如果您修复代码以使所有类型特征 onT现在都 on decltype(args),您将遇到一个新问题。当 args 是引用类型时,您期望的某些类型const不会是。那是因为没有const参考之类的东西。与第 1 项中的使用类似remove_pointer,您需要使用remove_reference来获取底层类型并检查是否为const.

于 2012-11-07T10:24:00.847 回答