15

In this response:

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

this program is given:

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>() << ' ';

I have no idea what the type of auto i is, making it harder to reuse expertise and learn from examples. Here is what changing auto i into char i returns

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) ===|

Try to figure out the type from that.

Is there a way to figure out what the type a variable of an auto is in C++11? To be more clear, I have a struct like this:

struct EventData
{
    // return value from redi::zip<std::vector<PriceQuote>, std::vector<PriceQuote>> what goes here????? So REDI::Zip is zipping PriceQuote, PriceQuote of bids and asks.
};

struct PriceQuote
{
   double price;
   double size;
};
4

8 回答 8

24

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

于 2013-07-23T18:25:38.300 回答
10

为什么要将该类型放入结构中?它并不是真的被设计成那样使用的(我应该知道,我写了它!)但如果有必要,你可以使用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;
};

注意你为什么要typedefstruct? 这是 C++ 而不是 C,停止它。

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

习惯它。你知道std::bind返回的类型吗?你知道std::mem_fn返回的类型吗?你知道 lambda 表达式创建的类型吗?不,你不需要知道,你只需要知道它有什么属性和你能用它做什么,而不是它叫什么或者它包含什么类型。

于 2013-07-23T21:30:30.610 回答
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>() << ' ';

更容易理解?

于 2013-07-23T18:34:37.027 回答
3

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

无论如何,您都需要查看它以输入您手动替换 'auto' 的任何内容,并且 auto 有很大的好处,它可以让您声明无法以其他方式声明的类型(如 lambda 返回,除非执行复杂的操作,例如decltype,它具有您不喜欢auto的相同缺陷)。

当 IDE 更多地支持 C++11 时,您的智能感知会更好地发挥作用,并且会更清楚类型是什么。我敢肯定,在一年或更短的时间内,大多数最新的 IDE 都会在鼠标悬停时告诉您auto的真实类型。

auto的收益远大于损失,但是,是的,有一点点损失会在良好的 IDE 支持下变得更小。几乎所有事情都有优点和缺点。

于 2013-07-23T18:26:38.443 回答
3

一个答案

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

回答:

尝试编译这样的东西:

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

编译器错误消息将告诉您“类型XXX(无论是什么)无法转换为int”。你有你的类型

于 2020-11-15T10:31:39.007 回答
2

我不同意您的断言,即不知道类型i是“使重用专业知识和从示例中学习变得更加困难”。的类型i是“zip返回的东西”。为什么还不够?

于 2013-07-23T18:35:27.020 回答
2

除了其他答案,我喜欢使用<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()from <typeinfo>

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

输出不像第一个示例那样易于理解,但仍然:

St4pairIiiE
于 2016-04-10T23:05:59.997 回答
1

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

ptype <varname>Linux:在 gdb 中调试代码并在 exe 与范围内的变量中断时提交。示例输出 - 在这种情况下,我可以替换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;
 }
于 2019-11-06T14:10:25.623 回答