替代对返回类型漠不关心的value_or
Alternative to value_or that is indifferent to the returned type
我构建了一个小类Card
重载<<
运算符,基本上打印出花色和卡片的值。
实现细节与我想在这里问的问题无关,只是假设显而易见的。Card
我建立了一个类CardDeck
。当然,CardDeck
可能会用完卡片。这促使我进行这种尝试:
std::optional<Card> CardDeck::drawCard() {
if (this->Cards.empty()) {
return std::nullopt;
}
else {
Card card = this->Cards.front();
this->Cards.pop_front();
return std::optional<Card>{card};
}
}
现在可以抽一张牌了,处理空牌组的可能性是使用CardDeck
的客户端代码的责任,但该方法并不总是返回值是冗长的。我喜欢这个解决方案。
无论如何,我做了天真的安萨茨C++新手:
std::cout<< cardDeck.drawCard().value_or("Out of cards!");
此操作失败,因为"Out of cards!"
的类型char*
但不是Card
。
我的问题:有没有办法在不检查和访问vaule/在两个不同的地方使用替代品的情况下保护优雅的oneliner?
在我的观点中处理这个问题的最简单方法是为std::optional<Card>
添加operator <<
重载。 在那里,您可以处理要打印的逻辑
std::ostream& operator <<(std::ostream& os, const std::optional<Card>& card)
{
if (card == std::nullopt)
return os << "Out of cards!";
else
return os << *card;
}
然后你可以拥有
std::cout << cardDeck.drawCard();
你可以为变量编写通用辅助std::visit
函数,但对于std::optional
,如下所示:
template <typename T, typename F, typename FEmpty>
auto my_optional_visit(const std::optional<T>& o, F f, FEmpty fEmpty)
{
return o ? f(*o) : fEmpty();
}
然后:
my_optional_visit(cardDeck.drawCard(),
[](const Card&c){ std::cout << c; },
[](){ std::cout << "Out of Cards!" });
我会使用一个函数(命名空间范围或卡片的静态成员(,该函数接受std::optional<Card>
并将其文本表示形式作为字符串返回。相关位将是:
class Card {
...
std::string repr() const {
std::string cr;
// writes the textual representation of a card here
return cr;
}
static std::string repr(const std::optional<Card> &card) {
if (card.has_value()) {
return card.value().repr();
}
return "Out of cards!";
}
};
std::ostream& operator << (std ostream& out, const Card& card) {
out << card.repr();
}
然后,您只需使用:
std::cout << Card::repr(cardDeck.drawCard());
C++函数只能有一个返回类型。在您的情况下,您希望在运行时确定结果的类型,每次调用结果时结果的类型可能会有所不同。这是不可能的。
如果你需要经常这样做,我建议只创建一个小的包装函数。
std::string optionalCardToString(const std::optional<Card> & card,
const std::string & emptyString) {
return card ? card->to_string() : emptyString;
}
std::cout << optionalCardToString(cardDeck.drawCard(), "Out of Cards");
如果性能是一个问题,你可以做很多事情来提高效率以避免制作副本,但总体思路是存在的。
我应该注意,在现实世界中,您不太可能从CarDeck
中绘制Card
并将其传送到cout
。您通常还想对卡执行其他操作,例如将其添加到Hand
或Pile
。这种需要做其他事情会否定你对必须多次提及值的担忧。
- 瓦尔格林德:数学函数"Conditional jump or move depends on uninitialised value(s)"
- C++核心准则 C35 对于接口类"A base class destructor should be either public and virtual, or protected and nonv
- 使用模板进行堆栈实现; "name followed by :: must be a class or namespace"
- 为什么static_assert错误:即使我传递常量"expression must have a constant value"?
- Android NDK clang 编译器错误在 Windows 上显示'No such file or directory'
- 为什么我会" void value not ignored as it ought to be"?
- 方法错误"not all control paths return a value"和方法不返回值
- 模式"allocate memory or use existing data"
- N-API include an .so or dll
- C++/SDL "initial value of reference to a non-const must be an lvalue"
- 已解决 - C++ 的崇高文本中的"fatal error: opencv: no such file or directory"
- 将 OR 逻辑运算符从 C++ 转换为 Fortran
- CPP 中的瓦尔格林德和记忆泄漏:"Conditional jump or move depends on uninitialised values"
- "error: subscripted value is not an array, pointer, or vector",我正在使用字符串
- C++ decltype(auto) or decltype(std::<T>forward(value))?
- 获取此地址时出现"expression must be an l-value or function designator"错误
- 我怎样才能写得"if not greater than or equal to some value"雄辩?
- 双链表实现中的"Conditional jump or move depends on uninitialised value"
- avl tree - Return False or Value C++
- 为什么使用非运算符时警告"forcing value to bool 'true' or 'false'"消失?