我正在尝试从std :: optional <>中的struct成员获取类型,该成员是成员函数的返回类型。
这是一个简化的示例:
struct Result
{
int tag;
int pos;
};
class Dict
{
public:
std::optional<Result> search(const char *word)
{
return Result{ 1,2 };
}
};
我希望能够做这样的事情:
int main()
{
Dict abc;
decltype(abc.search(const char*)->pos) position;
return 0;
}
答案 0 :(得分:6)
如果将实际参数传递给search
,它将起作用(以及将search
公开):
https://wandbox.org/permlink/0Q3mLW7SmQW4QshE
#include <optional>
struct Result
{
int tag;
int pos;
};
class Dict
{
public:
std::optional<Result> search(const char *word)
{
return Result{ 1,2 };
}
};
int main()
{
Dict abc;
decltype(abc.search("")->pos) position;
return 0;
}
search
的参数不必是有效的(就您的函数期望而言-因为实际上不会调用它),它必须是正确的类型。
如果您想直接处理类型而不是实例,正如您的注释所建议的那样,@ Jarod42指出您可以在变量声明中使用以下行:
decltype(std::declval<Dict>().search(std::declval<const char*>())->pos) position;
https://wandbox.org/permlink/kZlqKUFoIWv1m3M3
尽管我可能不需要指出〜70个字符变量类型的不可读性。我想如果是我,我要么只使用int
,要么为pos
创建类型别名,例如using ResultPositionType = int;
,然后在您的Result
结构中使用它,然后在main
中使用它。
答案 1 :(得分:0)
马克显示了您问题的直接答案。
但是,我提出了一个易于阅读的解决方案,它借用了标准库对类型别名的高度依赖。他们基本上是免费的,如果在类定义中有点吵:
#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;
}
这具有自我记录的优点,并且不需要仅C ++ Standardese母语者才能理解的70个字符的语句。 :)
它在类定义本身中也具有价值,因为现在您可以在一个地方设置这些类型,并且在语义允许的情况下,可以比过去更轻松地更改它们(当您不得不修改每个成员函数时) ,每个数据成员…)。
一个缺点是两个Result
成员的完整性并不那么明显。这是否有问题取决于您的实际代码,尤其是Result
的实际大小及其常用方式。作为一种折衷,您可以考虑在该级别上删除类型别名,仅保留Dict::ResultType
,然后使用decltype(declval<Dict::ResultType>().pos)
进行深入研究。只有您可以决定采用这种方法的程度。