Domanda

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;
};
È stato utile?

Soluzione 2

Why do you want to put that type in a struct? It's not really designed to be used like that (I should know, I wrote it!) but if necessary you can use decltype and std::declvalto determine the type (which will still give the right answer if I change the implementation of 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. why are you creating a typedef for the struct? This is C++ not C, stop it.

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

Get used to it. Do you know the type that std::bind returns? Do you know the type that std::mem_fn returns? Do you know the type that a lambda expression creates? No, you don't need to know, all you need to know is what properties it has and what you can do with it, not what it's called or what types it contains.

Altri suggerimenti

Try to change auto into a char and read the error message.

Would you have found

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

easier to understand?

An answer for

"How can I determine the actual type of an 'auto' variable at compile time"

Answer:

Try compiling something like this:

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

The compiler error message will tell you that "type XXX (whatever that is) cannot be converted to int". There you have your type

The best way to figure out what redi::zip() returns is to look at what redi::zip() returns. =) My IDE lets me jump straight to it by holding Ctrl and clicking zip(). Doesn't yours offer similar features? I can even just hover over zip() in the for() loop, and get a tooltip that gives the function signature - including the return type.

You'll need to look at it anyway for typing whatever you'd manually replace 'auto' with, and auto serves the great benefit that it lets you declare types that it's impossible to otherwise declare (like lambda returns, unless doing complex things like decltype, which has the same flaw you don't like about auto).

When IDEs support C++11 more, your intellisense would kick in better, and it'll be clearer what the type is. I'm sure in a year or less, most up-to-date IDEs will tell you the auto's true type when hovered over.

The gains of auto far outweigh the losses, though, yes, there is a tiny loss that will become even tinier with good IDE support. Almost everything has pros and cons.

I disagree with your assertion that not knowing the type of i is "making it harder to reuse expertise and learn from examples". The type of i is "that thing that zip returns". Why isn't that sufficient?

Apart from other answers, I like to use <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();
}

Which outputs:

std::pair<int, int>

You can also use typeid() from <typeinfo>:

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

The output is not as understandable as the first example, but still:

St4pairIiiE

Windows: The built-in debugger on Visual Studio will give you the type info.

Linux: debug the code in gdb and submit ptype <varname> when the exe breaks with the variable in scope. Example output - in this case I could replace auto with vector<uint8_t>::const_iterator but that isn't particularly obvious from this:

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;
 }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top