【发布时间】:2018-06-05 15:55:11
【问题描述】:
我正在试验一些静态多态技术和 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 所做的事情,只允许将动物传递给函数。我不确定这是否可能?
【问题讨论】:
标签: c++ templates c++17 variant crtp