【发布时间】:2021-10-03 11:32:13
【问题描述】:
我有以下使用 std::variant 的示例:
#include <iostream>
#include <string>
#include <variant>
class Cat {
public:
const std::string& getSound() const { return sound; };
private:
std::string sound = "Meow.";
};
class Dog {
public:
const std::string& getSound() const { return sound; };
private:
std::string sound = "Bark.";
};
class House {
public:
void resetAnimal(const auto&& animal) { v = std::move(animal); }
const auto& getAnimal() const {
return std::visit([](const auto& animal) -> decltype(animal)&
{ return animal; }, v);
}
private:
std::variant<Cat, Dog> v;
};
int main() {
House house;
house.resetAnimal(Cat());
std::cout << house.getAnimal().getSound() << std::endl;
house.resetAnimal(Dog());
std::cout << house.getAnimal().getSound() << std::endl;
return 0;
}
有趣的是,它可以使用从 g++-8 到 g++-10 的编译器进行编译。 (使用标志 -std=c++17 和 -fpermissive)并且在使用 g++-11 时失败。如果它编译,它会按预期工作 - 打印“喵”。和“树皮”。在不同的行上。错误消息如下所示(g++-11):
In file included from <source>:3:
/opt/compiler-explorer/gcc-11.1.0/include/c++/11.1.0/variant: In instantiation of 'constexpr decltype(auto) std::visit(_Visitor&&, _Variants&& ...) [with _Visitor = House::getAnimal() const::<lambda(const auto:23&)>; _Variants = {const std::variant<Cat, Dog>&}]':
<source>:25:26: required from here
/opt/compiler-explorer/gcc-11.1.0/include/c++/11.1.0/variant:1758:29: error: static assertion failed: std::visit requires the visitor to have the same return type for all alternatives of a variant
1758 | static_assert(__visit_rettypes_match,
| ^~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-11.1.0/include/c++/11.1.0/variant:1758:29: note: '__visit_rettypes_match' evaluates to false
<source>: In member function 'const auto& House::getAnimal() const':
<source>:26:48: error: forming reference to void
26 | { return animal; }, v);
| ^
Compiler returned: 1
在使用 MSVC 进行编译时,我得到了一个含义非常接近的消息。 我的问题是:
- 是否可以使用
g++-11编译示例代码?如果答案是“是”,那该怎么做? - 为什么添加
-fpermissive会使 g++ 编译器在这种情况下工作? - 是否可以使用 MSVC 编译示例代码?
- 是否可以使用 clang 进行编译? (我试过了。)
附:我知道继承和模板。我只是有兴趣,是否可以按照我在示例中的方式进行操作。
【问题讨论】:
-
decltype(std::declval<House>().getAnimal())应该是什么?
标签: c++ visual-c++ g++ clang c++17