I'm working on code for a container that stores strings and sorts them in alphabetical order (thought that it'd be a fun idea). I've been attempting to put a "[]" operator and assign it to the private member words so I can access any data or strings inside of said member. However, I've been struggling with this continuous error that I'm having trouble fixing. It says:
No operator "[]" matches these operands. Operand types are std::shared_ptr<std::vector<std::string, std::allocator<std::string>>>[size_t]
Here's some of the code regarding the error (Error is present at class.cpp):
class.h
#pragma once
#include <memory>
#include <vector>
#include <string>
#include <iostream>
class sort
{
public:
//...
sort(int i): words(std::make_shared<std::vector<std::string>>(i)) { }
std::shared_ptr<std::vector<std::string>> & operator [](size_t st);
//...
private:
std::shared_ptr<std::vector<std::string>> words;
std::string alpha = "abcdefghijklmnopqrstuvwxyz";
};
class.cpp
#include "sort.h"
#include <memory>
#include <vector>
#include <iostream>
//...
std::shared_ptr<std::vector<std::string>> & sort::operator[](size_t st)
{
return words[st]; //Error is defined at the brackets
}
//...
Another thing to note is that if I remove the brackets with st, the error is gone (Obviously not what I'm trying to achieve). Any help or a fix to this code would be greatly appreciated.
2 Answers 2
Your words member is not an array or container. It is a std::shared_ptr, which does not have an operator[] defined prior to C++17 (and even then, your code would still be using it wrong). That is why your operator[] fails to compile.
You have a std::shared_ptr pointing to a std::vector<std::string> object stored somewhere else in memory 1. If you want your operator[] to access the std::string values in that std::vector, you need to deference the pointer first in order to access the std::vector, and then you can call its operator[]. You need to fix the return value of your operator[] to be a single std::string, not a std::shared_ptr.
1: why are you using a pointer at all? Why not declare words to be an actual std::vector object directly in your class? std::vector<std::string> words;
Try this instead:
class.h
#pragma once
#include <memory>
#include <vector>
#include <string>
#include <iostream>
class sort
{
public:
//...
std::string& operator [](size_t st);
//...
private:
std::shared_ptr<std::vector<std::string>> words;
std::string alpha = "abcdefghijklmnopqrstuvwxyz";
};
class.cpp
#include "sort.h"
#include <memory>
#include <vector>
#include <iostream>
//...
std::string& sort::operator[](size_t st)
{
return (*words)[st];
}
//...
The problem is probably the fact that words is a std::shared_ptr, not an std::vector. std::shared_ptr::operator[]() is a C++17 thing (meaning it won't compile in C++11), and even then it doesn't do what you think it does:
Return value
A reference to the idx-th element of the array, i.e., get()[idx]
Then, from get()'s documentation:
std::shared_ptr::get
T* get() const noexcept; (until C++17)
element_type* get() const noexcept; (since C++17)
Meaning that get() returns a pointer. Together, this effectively makes your code the same as:
std::vector<int>* ptr = nullptr; // Note that this data is probably allocated some how...
// Then, later...
ptr[index];
That is not what is appears you want. This is basically the functional equivalent of accessing the indexth element of an array of vectors (it's more complicated than that, but I don't know enough about the technical differences between pointers and arrays to articulate it properly here). What you want is the operator[]() of the dereferenced pointer like this:
(*ptr)[index]; // Parenthesis for clarity. I don't think that they are technically necessary here.
What this boils down to is this: what you (probably) want is std::shared_ptr's dereference operator:
return (*words)[st]; // again, parenthesis for clarity here.
// I don't think they are technically necessary here, either.
That should compile and do what you want.
Edit: It has come to my attention, thanks to Remy Lebeau's answer, that your function prototype will need to change as well, as (*words)[st] is not a std::shared_ptr<std::vector<std::string>>, it is merely as std::string. Thus, change the prototype to this instead:
std::string& operator [](size_t st);
And in the cpp:
std::string& sort::operator[](size_t st) { return (*words)[st]; }
wordsisstd::shared_ptr<std::vector<std::string>>. Why would you expect anoperator[]for it to ALSO produce astd::shared_ptr<std::vector<std::string>>?? More conventional usage ofoperator[]is to produce an element of a container e.g.std::string::operator[]()produces a (reference to) achar. Also, having a class member that isstd::shared_ptr<std::vector<string>>is pointless - a member that is a simplestd::vector<std::string>is correct - and less error prone. And a class namedsort.... Bleegh!