lukeisme
lukeisme

Reputation: 11

When using std set find, the program will not compile

I'm trying to find a string in a std::set, but when using std::set::find, it produces a very long error that I do not understand. I can access the set from the program, so that is not the issue.

When I just run the find, it works fine, but when I use it in anything, like setting it to a variable or trying to output it, the compiler freaks out. I see that the errors are coming from a c++ 7 folder, but this is supposed to be c++11, so I don't know.

Here is where I am trying to use the command:

int interperet() {
  cout << ">"; 
  if (!cin.getline(input,sizeof(input))) {
    cout << "ErrCode 1: Could not get input" << endl;
  }

  cout << commands.find("help cmmds.cpp");


  return 0;
}

Here is the set:

set<string> commands = {
  "help cmmds.cpp"
};

Here is a pastebin of the compiler output: https://pastebin.com/U6dfy8Lq

Am I correct in saying that the error claims that it cannot convert std::__cxx11::basic_string<char> to std::__cxx11::basic_string<char>?

Thank you for your help!

Upvotes: 1

Views: 518

Answers (3)

eerorika
eerorika

Reputation: 238491

Am I correct in saying that the error claims that it cannot convert std::__cxx11::basic_string to std::__cxx11::basic_string?

No. That would not be accurate.

The error claims that it cannot convert std::set<std::__cxx11::basic_string<char>, std::less<std::__cxx11::basic_string<char> >, std::allocator<std::__cxx11::basic_string<char> > >::iterator to any of the candidates of overload set for operator<<(basic_ostream<_CharT, _Traits>&, .....

Let us call that type set::iterator for conciseness. That is what set::find returns and what you've attempted to insert into the output stream.


You'll need to decide what you inteded by your attempt to insert an iterator into the output stream.

If your intention is to print whether a value exists in the set, you can use this instead:

// only since C++20
cout << commands.contains("help cmmds.cpp");
// pre C++20
cout << commands.find("help cmmds.cpp") != commands.end();

If your intention is to print the string, you could use:

const char* str = "help cmmds.cpp";
if (commands.contains(str))
    cout << str;

Or you could indirect through the returned iterator. But you must first check whether it was found:

auto it = commands.find("help cmmds.cpp");
if (it != commands.end())
    std::cout << *it;

Upvotes: 1

Loki Astari
Loki Astari

Reputation: 264739

The type returned by std::set<T>::find() is an Iterator.

You can not pass Iterators to output streams (generally speaking). But you can de-reference the iterator to get a reference to T and if this is streamable via operator<< then it will print.

auto find = commands.find("X");
std::cout << (*find) << "\n;
              ^  // de-reference the iterator.

Now don't write the code like I have done above. The problem here is that find may fail. If the find fails it returns the end() iterator for the container. It is undefined behavior to de-reference the end() iterator so you must really check for this.

auto find = commands.find("X");
if (find != commands.end()) {
    std::cout << (*find) << "\n;
} else {
    std::cout << "Failed\n";
}

Upvotes: 3

Gem Taylor
Gem Taylor

Reputation: 5635

Find returns an object of type Container::iterator

http://www.cplusplus.com/reference/set/set/find/

Generally those objects don't support print/streaming methods.

What you probably want to know is whether it was found, so you could stream (commands.find("help cmmds.cpp") != commands.end()) instead.

Upvotes: 1

Related Questions