Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Auto type to auto method fails. Why?

Tags:

c++

stl

c++14

auto

As a learning exercise I am building a class to manage the old familiar argc and argv values to main. I am storing argv as a std::vector of std::strings. For the moment I would like to loop over my object as if it was the vector. The problem I'm having is that my solution becomes highly dependent on my choice of container and the compiler breaks when I try to fix it. Observe:

This is the way I would like my class to work for this example.

int main(int argc, char* argv) {
  CLI options(argc, argv);

  for (auto option : options) {
    cout << option << endl;
  }
}

This is fairly trivial, but did require a moment of research. Here is my header file

typedef char* cstring;

class CLI {
  std::vector<std::string> arguments;
public:
  CLI(const int argc, const cstring argv[]);

  std::vector<std::string>::const_iterator begin();
  std::vector<std::string>::const_iterator end();
};

and my source file for the CLI class. (minus includes etc)

CLI::CLI(const int argc, const cstring argv[]) {
  arguments = std::vector<std::string>(argv, argv + argc);
}

std::vector<std::string>::const_iterator CLI::begin() {
  return arguments.begin();
}

std::vector<std::string>::const_iterator CLI::end() {
  return arguments.end();
}

This works beautifully, but here is my first problem. If I decide that I wish to use a linked list instead of a vector, I now have at least five spots that need to change, more if my client code is having a silly day and doesn't use auto for its loop (or whatever else it does). This feels like it should be a case of auto-to-the-rescue! With the new C++ features I should be able to change the method signature to this:

... // Header
auto begin();

... // Source
// Possibly without the decltype now? Not sure how or when...
auto CLI::begin() -> decltype(arguments.begin()) {
  return arguments.begin();
}

This is where I finally get an error:

.../main.cpp: In function ‘int main(int, char**)’:
.../main.cpp:10:22: error: use of ‘auto CLI::begin()’ before deduction of ‘auto’
   for (auto option : options) {
                      ^
.../main.cpp:10:22: error: invalid use of ‘auto’

Okay. If I had to guess as to what this meant, I would say the auto in the for loop is looking up the signature for the begin method, hoping to find a concrete return type. What it finds instead is auto, and panics.

So, is this theory correct, and is there a better way to hide the container type despite the iterators?

P.S. The more I look at this problem, the more I am realizing that this functionality is probably not functionality I want in the final product anyways. But this still seems like an opportunity to learn something.

like image 952
Jwashton Avatar asked Oct 31 '22 12:10

Jwashton


1 Answers

Since the header does not include code, the compilation unit for main.cpp cannot deduce the meaning of auto for begin()

This would work better for what you intend:

Header.h

#include <vector>                                                                  

class A {
public:
        std::vector<int> a;
        decltype(a.begin()) begin();
        decltype(a.cbegin()) cbegin() const;
};

Header.cpp

#include "header.h"
decltype(A::a.begin()) A::begin() {
        return a.begin();
}
decltype(A::a.cbegin()) A::cbegin() const {
        return a.cbegin();
}

main.cpp

#include "header.h"
int main(int argc, char **argv) {
        A a;
        auto b = a.begin();
        auto cb = a.cbegin();
        return 0;                                                               
}

A note on const safety: remember that a "const_iterator" is a unique type that is not necessarily const itself but that the object it represents is const. This means that the type is different which prevents you from returning a.begin() inside of a const function. The naive might try adding const decltype(a.begin()) return type but that is still not a vector::const_iterator but rather a const vector::iterator.

like image 122
inetknght Avatar answered Nov 11 '22 16:11

inetknght