Понимаю что исходный код достаточно большой, но все же, надеюсь кто то да подскажет.
Пытаюсь разобраться с кодом из книги Lippman С++ Primer, конец 15 главы.
Возможно я что то неправильно понимаю, но почему в `main` в строке:
Query query = Query("she") & Query("is");
копирующий конструктор
Query вызывается всего 2 раза при вызове конструктора
BinaryQuery, когда происходит инициализация
lhs и
rhs, но не вызывается когда собственно инициализируется переменная
query в функции
main?
Собственно и не могу понять каким образом инициализируется эта переменная если не при помощи копирующего конструктора.
Как я понял, алгоритм выполнения следующий:
1. Создается файловый поток
2. Создается объект класса `TextQuery`
3. Вызывается конструктор `Query(string)` с аргументом `"she"` (внутри вызывается `WordQuery(string)`)
4. Вызывается конструктор `Query(string)` с аргументом `"is"` (внутри вызывается `WordQuery(string)`)
5. Вызывается оператор `&` с двумя аргументами
6. Вызывается конструктор `AndQuery` в который передаются оба операнда
7. Вызывается конструктор `BinaryQuery` в котором происходит инициализация lhs и rhs с помощью копирующего конструктор `Query`
8. Далее вызывается конструктор `Query` с параметром `shared_ptr`, после чего q ссылается на AndQuery объект
9.
И вот тут по моему должен вызываться копирующий конструктор `Query` чтобы произошла инициализация переменной `query` в функции `main`, но почему то этого не происходит...
Исходный код:
spoilerusing namespace std;
class QueryResult
{
public:
using line_no = vector<string>::size_type;
QueryResult(string sw, shared_ptr<set<line_no>> ln, shared_ptr<vector<string>> ft) : sought_word(sw), lines_numbers(ln), file_text(ft) {}
auto begin() const { return lines_numbers->begin(); }
auto end() const { return lines_numbers->end(); }
auto get_file() const { return file_text; }
private:
string sought_word;
shared_ptr<set<line_no>> lines_numbers;
shared_ptr<vector<string>> file_text;
};
class TextQuery
{
public:
using line_no = vector<string>::size_type;
TextQuery(ifstream& is) : file_text(new vector<string>)
{
string line;
while (getline(is, line))
{
file_text->push_back(line);
istringstream line_stream(line);
string word;
while (line_stream >> word)
{
auto& lines_numbers = words_map[word];
if (!lines_numbers) lines_numbers.reset(new set<line_no>);
lines_numbers->insert(file_text->size() - 1);
}
}
}
QueryResult query(const string& sought_word) const
{
static shared_ptr<set<line_no>> no_data(new set<line_no>);
auto loc = words_map.find(sought_word);
if (loc == words_map.end()) return QueryResult(sought_word, no_data, file_text);
else return QueryResult(sought_word, loc->second, file_text);
}
private:
shared_ptr<vector<string>> file_text;
map<string, shared_ptr<set<line_no>>> words_map;
};
class QueryBase
{
friend class Query;
protected:
using line_no = TextQuery::line_no;
virtual ~QueryBase() = default;
private:
virtual QueryResult eval(const TextQuery&) const = 0;
virtual string rep() const = 0;
};
class Query
{
friend Query operator~(const Query&);
friend Query operator|(const Query&, const Query&);
friend Query operator&(const Query&, const Query&);
friend ostream& operator<<(ostream&, const Query&);
public:
Query(const string&);
Query(const Query& query)
{
cout << "Here..." << endl;
q = query.q;
}
QueryResult eval(const TextQuery& t) const { return q->eval(t); }
string rep() const { return q->rep(); }
private:
Query(shared_ptr<QueryBase> query) : q(query) {}
shared_ptr<QueryBase> q;
};
ostream& operator<<(ostream& os, const Query& query)
{
return os << query.rep();
}
class WordQuery : public QueryBase
{
friend class Query;
private:
WordQuery(const string& s) : query_word(s) {}
QueryResult eval(const TextQuery& t) const { return t.query(query_word); }
string rep() const { return query_word; }
string query_word;
};
inline Query::Query(const string& s) : q(new WordQuery(s)) {}
class BinaryQuery : public QueryBase
{
protected:
BinaryQuery(const Query& l, const Query& r, string s) : lhs(l), rhs(r), op_sym(s) {}
string rep() const { return "(" + lhs.rep() + " " + op_sym + " " + rhs.rep() + ")"; }
Query lhs;
Query rhs;
string op_sym;
};
class AndQuery : public BinaryQuery
{
friend Query operator&(const Query&, const Query&);
AndQuery(const Query& left, const Query& right) : BinaryQuery(left, right, "&") {}
QueryResult eval(const TextQuery& text) const
{
auto left = lhs.eval(text);
auto right = rhs.eval(text);
auto ret_lines = make_shared<set<line_no>>();
set_intersection(left.begin(), left.end(), right.begin(), right.end(), inserter(*ret_lines, ret_lines->begin()));
return QueryResult(rep(), ret_lines, left.get_file());
}
};
inline Query operator&(const Query& lhs, const Query& rhs)
{
auto temp = shared_ptr<QueryBase>(new AndQuery(lhs, rhs));
return Query(temp);
}
int main()
{
ifstream file("./file.txt");
TextQuery text_query(file);
Query query = Query("she") & Query("is"); // ???????????????????????
print(cout, query.eval(text_query));
return 0;
}