我正在尝试从结构成员中获取类型,该类型位于一个std::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(const char*)->pos) position;
return 0;
}发布于 2019-02-06 17:31:51
如果您将一个实际参数传递给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中再次使用。
发布于 2019-02-06 22:43:45
Mark给出了你问题的直接答案。
但是,我提出了一个更易于阅读的解决方案,它借用了标准库对类型别名的严重依赖。它们基本上是免费的,尽管在类定义中有一点嘈杂:
#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++标准语言使用者才能理解的70个字符的语句。:)
它在类定义本身中也有价值,因为现在您有了一个地方来设置这些类型,并且在语义允许的情况下,可以比过去更容易地更改它们(当您必须修改每个成员函数、每个数据成员…时)。。
一个缺点是,两个Result成员的内在性并不是很明显。这是否是一个问题取决于您的实际代码,特别是Result的实际大小以及它的常用用法。作为一种折衷方案,您可以考虑删除该级别的类型别名,只保留Dict::ResultType,然后使用decltype(declval<Dict::ResultType>().pos)深入研究它。只有你才能决定这种方法要走多远。
https://stackoverflow.com/questions/54550253
复制相似问题