我可以使用特征指定变体的类型列表吗?



我正在尝试一些静态多态技术和 c++17 模板。我已经设法使用 CRTP 实现了多态性,然后使用变体容器来存储我的类型,这样它们就不需要公共基类(这将使我回到运行时多态性(。

#include <iostream>
#include <memory>
#include <vector>
#include <variant>
template <typename T>
class Animal
{
public:
virtual ~Animal() = default;
void noise()
{
derived()->noiseImpl();
}
private:
void noiseImpl()
{
std::cout<<"Animal animal!n";
}
T* derived() {return static_cast<T*>(this);}
};
class Dog : public Animal<Dog>
{
private:
friend Animal;
void noiseImpl()
{
std::cout<<"Woof woof!n";
}
};
class Cat : public Animal<Cat>
{
private:
friend Animal;
void noiseImpl()
{
std::cout<<"Meow meow!n";
}
};
template <
typename T,
typename TD = std::decay_t<T>,
typename = typename std::enable_if_t<std::is_base_of_v<Animal<TD>, TD>>
>
void pet(T&& animal)
{
animal.noise();
}
int main()
{
std::vector<std::variant<Dog, Cat>> animals;
animals.emplace_back(Dog{});
animals.emplace_back(Cat{});
for (auto& a : animals)
{
std::visit([](auto&& arg) 
{
pet(arg);
}, a);
}
}

上面的示例的行为符合您的预期,但是我现在想做的是不需要指定变体的类型。相反,我希望编译器确定从 Animal 继承的所有类型,并创建一个可以容纳所有这些类型的变体。这类似于pet函数使用is_base_of所做的操作,只允许将动物传递给函数。我不确定这是否可能?

我认为不可能自动确定从基类继承的所有类。通常,这是无法实现的,因为可以在不同的编译单元中定义不同的继承类。

您可以做的是在某个 MPL 类型序列中"注册"这些继承的类,然后使用它来定义您的variant类型。例如,boost::hana

constexpr auto types = boost::hana::tuple_t<char, short, int, long>;
using variant = decltype(boost::hana::unpack(
types, boost::hana::template_<std::variant>))::type;
static_assert(std::is_same_v<variant, std::variant<char, short, int, long>>);

在您的情况下,这将是:

constexpr auto types = boost::hana::tuple_t<Dog, Cat>;

相关内容

  • 没有找到相关文章

最新更新