Код: Выделить всё
std::visitmy -код:
Код: Выделить всё
#include
#include
#include
#include
#include
namespace variant_shapes {
// 圆形实现 - 不使用虚函数
class Circle {
private:
double radius_;
public:
explicit Circle(double radius) : radius_(radius) {}
double area() const {
return M_PI * radius_ * radius_;
}
double getRadius() const { return radius_; }
};
// 矩形实现 - 不使用虚函数
class Rectangle {
private:
double width_;
double height_;
public:
Rectangle(double width, double height) : width_(width), height_(height) {}
double area() const {
return width_ * height_;
}
double getWidth() const { return width_; }
double getHeight() const { return height_; }
};
}
// 添加一个直接使用 if constexpr 的基准测试
static void BM_StaticDispatch(benchmark::State& state) {
std::vector shapes;
shapes.reserve(1000);
for (int i = 0; i < 1000; ++i) {
if (i % 2 == 0) {
shapes.emplace_back(variant_shapes::Circle(5.0));
} else {
shapes.emplace_back(variant_shapes::Rectangle(4.0, 6.0));
}
}
auto visitor = [](auto &&arg) -> double
{
using T = std::decay_t;
if constexpr (std::is_same_v)
{
return arg.area();
}
else if constexpr (std::is_same_v)
{
return arg.area();
}
};
for (auto _ : state) {
double totalArea = 0.0;
for (const auto& s : shapes) {
totalArea += std::visit(visitor, s);
}
benchmark::DoNotOptimize(totalArea);
}
}
BENCHMARK(BM_StaticDispatch);
// std::variant + std::visit 基准测试
// 使用 if constexpr 的静态分派函数
template
double get_area(const T& shape) {
if constexpr (std::is_same_v) {
return shape.area();
} else if constexpr (std::is_same_v) {
return shape.area();
}
return 0.0; // 不应该到达这里
}
static void BM_StaticDispatch2(benchmark::State& state) {
std::vector shapes;
shapes.reserve(1000);
for (int i = 0; i < 1000; ++i) {
if (i % 2 == 0) {
shapes.emplace_back(variant_shapes::Circle(5.0));
} else {
shapes.emplace_back(variant_shapes::Rectangle(4.0, 6.0));
}
}
auto visitor = [](auto &&arg) -> double
{
using T = std::decay_t;
if constexpr (std::is_same_v)
{
return arg.area();
}
else if constexpr (std::is_same_v)
{
return arg.area();
}
};
for (auto _ : state) {
double totalArea = 0.0;
for (const auto& s : shapes) {
totalArea += s.index() == 0
? get_area(std::get(s))
: get_area(std::get(s));
}
benchmark::DoNotOptimize(totalArea);
}
}
BENCHMARK(BM_StaticDispatch2);
Подробнее здесь: https://stackoverflow.com/questions/796 ... nefficient