如何确定'auto'变量的实际类型

时间:2013-07-23 18:20:21

标签: c++ c++11 auto

在此回复中:

https://stackoverflow.com/a/14382318/1676605

这个程序是:

std::vector<int> vi{ 0, 2, 4 };
std::vector<std::string> vs{ "1", "3", "5", "7" };
for (auto i : redi::zip(vi, vs))
    std::cout << i.get<0>() << ' ' << i.get<1>() << ' ';

我不知道auto i的类型是什么,使得重用专业知识和从示例中学习变得更加困难。以下是将auto i更改为char i的内容

In function ‘int main()’:|
/data/cbworkspace/TestZip/TestZip.cpp|14|error: cannot convert ‘boost::iterator_facade<boost::zip_iterator<boost::tuples::tuple<__gnu_cxx::__normal_iterator<int*, std::vector<int> >, __gnu_cxx::__normal_iterator<int*, std::vector<int> > > >, boost::tuples::cons<int&, boost::tuples::cons<int&, boost::tuples::null_type> >, boost::random_access_traversal_tag, boost::tuples::cons<int&, boost::tuples::cons<int&, boost::tuples::null_type> >, long int>::reference {aka boost::tuples::cons<int&, boost::tuples::cons<int&, boost::tuples::null_type> >}’ to ‘char’ in initialization|
/data/cbworkspace/TestZip/TestZip.cpp|14|warning: unused variable ‘i’ [-Wunused-variable]|
||=== Build finished: 1 errors, 1 warnings (0 minutes, 0 seconds) ===|

尝试从中找出类型。

有没有办法弄清楚{+ 1}} 的变量在C ++ 11中的类型?为了更清楚,我有auto这样的:

struct

8 个答案:

答案 0 :(得分:14)

尝试将auto更改为char并阅读错误消息。

答案 1 :(得分:9)

为什么要将该类型放在结构中?它并不是真的被设计成这样使用(我应该知道,我写了它!)但是如果有必要,你可以使用decltypestd::declval来确定类型(如果我仍然会给出正确的答案)改变redi::zip

的实施
struct EventData
{
  // type returned by redi::zip
  typedef decltype(redi::zip(std::declval<V1>(), std::declval<V2>())) zipper_type;

  // type referred to by zipper_type::iterator
  typedef std::iterator_traits<zipper_type::iterator>::value_type zipped_type;

  zipper_type m_zipper;
};

N.B。为什么要为typedef创建struct?这是C ++而不是C,停止它。

  

我不知道auto i的类型是什么,使得重用专业知识和从示例中学习变得更加困难。

习惯它。你知道std::bind返回的类型吗?你知道std::mem_fn返回的类型吗?你知道lambda表达式创建的类型吗?不,您不需要知道,您需要知道的是它具有哪些属性以及您可以用它做什么,而不是它的名称或它包含的类型。

答案 2 :(得分:8)

你找到了吗

for (boost::iterator_facade<
       boost::zip_iterator<
         boost::tuples::tuple<std::vector<int>::iterator,
                              std::vector<int>::iterator>
       >,
       boost::tuples::cons<int&, boost::tuples::cons<int&, boost::tuples::null_type> >,
       boost::random_access_traversal_tag,
       boost::tuples::cons<int&, boost::tuples::cons<int&, boost::tuples::null_type> >,
       long int
     >::reference i : redi::zip(vi, vs))
    std::cout << i.get<0>() << ' ' << i.get<1>() << ' ';

更容易理解?

答案 3 :(得分:3)

找出redi::zip()返回的最佳方法是查看redi::zip()返回的内容。 =) 我的IDE让我通过按住Ctrl并单击zip()直接跳到它。你们不提供类似的功能吗? 我甚至可以将鼠标悬停在zip()循环中的for()上,并获得一个提供函数签名的工具提示 - 包括返回类型。

无论如何你都需要查看它来键入你手动替换'auto'的内容,并且auto会提供很大的好处,它可以让你声明那些不可能声明的类型(比如lambda返回,除非做复杂的东西,如decltype,它有你不喜欢 auto 的相同缺陷。

当IDE更多地支持C ++ 11时,你的intellisense会更好地发挥作用,而且类型更清晰。我确信在一年或更短的时间内,大多数最新的IDE会在悬停时告诉你 auto 的真实类型。

auto 的收益远远超过了损失,但是,有一个很小的损失会在IDE支持良好的情况下变得更加微弱。几乎所有事情都有利有弊。

答案 4 :(得分:2)

我不同意你的断言,即不知道i的类型“使得重用专业知识并从示例中学习更难”。 i的类型是“zip返回的内容”。为什么这还不够?

答案 5 :(得分:1)

除了其他答案,我还想使用<boost/type_index.hpp>

int main()
{
    using namespace std;
    using namespace boost::typeindex;

    auto p = std::make_pair(1, 2);
    cout << type_id_with_cvr<decltype(p)>().pretty_name();
}

哪个输出:

std::pair<int, int>

您还可以使用typeid()中的<typeinfo>

auto p = std::make_pair(1, 2);
cout << typeid(p).name() << '\n';

输出不像第一个例子那样容易理解,但仍然是:

St4pairIiiE

答案 6 :(得分:0)

Windows:Visual Studio上的内置调试器将为您提供类型信息。

Linux:在exe中断作用域中的变量时,调试gdb中的代码并提交ptype <varname>。输出示例-在这种情况下,我可以将auto替换为vector<uint8_t>::const_iterator,但这并不是特别明显:

type = class __gnu_cxx::__normal_iterator
                  <unsigned char const*,
                   std::vector<unsigned char,
                               std::allocator<unsigned char>
                              > 
                  >
       [with _Iterator = const unsigned char *, 
       _Container = std::vector<unsigned char, std::allocator<unsigned char> >] 
        {
   protected:
       _Iterator _M_current;

   public:
     __normal_iterator(void);
     __normal_iterator(const unsigned char * const&);
     reference operator*(void) const;
     _Iterator operator->(void) const;
     __gnu_cxx::__normal_iterator<unsigned char const*, _Container> & operator++(void);
     __gnu_cxx::__normal_iterator<unsigned char const*, _Container> operator++(int);
     __gnu_cxx::__normal_iterator<unsigned char const*, _Container> & operator--(void);
     __gnu_cxx::__normal_iterator<unsigned char const*, _Container> operator--(int);
     reference operator[](difference_type) const;
     __gnu_cxx::__normal_iterator<unsigned char const*, _Container> & operator+=(difference_type);
     __gnu_cxx::__normal_iterator<unsigned char const*, _Container> operator+(difference_type) const;
     __gnu_cxx::__normal_iterator<unsigned char const*, _Container> & operator-=(difference_type);
    __gnu_cxx::__normal_iterator<unsigned char const*, _Container> operator-(difference_type) const;

     const unsigned char * const& base(void) const;
     void __normal_iterator<unsigned char*>(const
                        __gnu_cxx::__normal_iterator<unsigned char*, _Container> &);

     typedef std::iterator_traits<unsigned char const*>::reference reference;
     typedef _Iterator pointer;
     typedef std::iterator_traits<unsigned char const*>::difference_type difference_type;
     typedef std::iterator_traits<unsigned char const*>::iterator_category iterator_category;
 }

答案 7 :(得分:0)

答案

“在编译时如何确定'auto'变量的实际类型

答案:

尝试编译如下内容:

auto foo = function_that_returns_unknown_type() // "what type could foo be?"
int a = foo;

编译器错误消息将告诉您“类型XXX(无论是哪种类型)都不能转换为int”。在那里输入文字