Марк показал прямой ответ на ваш вопрос.
Однако я предлагаю более простое для чтения решение, которое заимствует большую зависимость стандартной библиотеки от псевдонимов типов.Они в основном бесплатны, хотя и немного шумны в определениях классов:
#include <optional>
struct Result
{
using TagType = int;
using PosType = int;
TagType tag;
PosType pos;
};
class Dict
{
public:
using ResultType = Result;
std::optional<ResultType> search(const char* word)
{
return ResultType{ 1, 2 };
}
};
int main()
{
Dict abc;
Dict::ResultType::PosType position;
}
Преимущество этого заключается в самодокументировании и отсутствии необходимости в выражении из 70 символов, которое могут понять только носители языка C ++ Standardese.:)
Он также имеет значение внутри самих определений классов, потому что теперь у вас есть одно место для установки этих типов, и, если позволяет семантика, их можно изменить легче, чем в прошлом (когда вам приходилосьизменить каждую функцию-член, каждый элемент данных…).
Недостатком является то, что сущность двух Result
членов не так очевидна.Является ли это проблемой, зависит от вашего реального кода, в частности от фактического размера Result
и от того, как он часто используется.В качестве компромисса вы можете рассмотреть возможность удаления псевдонимов типов на этом уровне, сохраняя только Dict::ResultType
, а затем копаясь в нем с помощью decltype(declval<Dict::ResultType>().pos)
.Только вы можете решить, как далеко зайти с этим подходом.