You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@doris.apache.org by ya...@apache.org on 2026/04/15 15:20:26 UTC
(doris) branch master updated: [refine](function) enforce `final` on CRTP aggregate function derived classes to enable compiler devirtualization (#62433)
This is an automated email from the ASF dual-hosted git repository.
yanxuecheng pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new 4e81acee0d8 [refine](function) enforce `final` on CRTP aggregate function derived classes to enable compiler devirtualization (#62433)
4e81acee0d8 is described below
commit 4e81acee0d83e1db3100a0eb8fe820d05c833c31
Author: Mryange <ya...@selectdb.com>
AuthorDate: Wed Apr 15 23:20:16 2026 +0800
[refine](function) enforce `final` on CRTP aggregate function derived classes to enable compiler devirtualization (#62433)
`IAggregateFunctionHelper<Derived>` implements hot aggregate paths such
as `add_batch()` and `add_batch_single_place()` by calling
`assert_cast<const Derived*>(this)->add(...)`. Because `add()` is
declared `virtual` in `IAggregateFunction`, the compiler cannot
devirtualize this call unless it can prove that `Derived` has no further
overrides — which requires `Derived` to be marked `final`.
This PR enforces this via a `static_assert` in the
`IAggregateFunctionHelper` constructor. Note that `final` here is a
**performance hint only** — correctness is not affected, since `add()`
remains virtual and subclasses always dispatch correctly through the
vtable regardless. Marking `Derived` as `final` allows the compiler to
devirtualize (and potentially inline) the `add()` call inside hot
aggregation paths.
Changes:
1. Add a `static_assert` in the `IAggregateFunctionHelper` constructor
asserting `std::is_final_v<Derived>`, so that missing `final` is caught
at compile time.
2. Introduce `AggregateFunctionNonFinalBase` as an opt-out marker for
classes that intentionally form inheritance hierarchies (e.g.
`AggregateStateUnion → AggregateStateMerge`, `AggregateFunctionForEach →
AggregateFunctionForEachV2`).
3. Mark all concrete aggregate function classes `final` across
`be/src/exprs/aggregate/`.
4. Refactor `AggregateFunctionTopNBase` to accept a `Derived` template
parameter so that `AggregateFunctionTopN` and
`AggregateFunctionTopNArray` can each be marked `final`.
5. Refactor `AggregateFunctionPercentileApprox` into
`AggregateFunctionPercentileApproxBase<Derived>` so the four concrete
specializations can each be marked `final`.
---
be/src/exprs/aggregate/aggregate_function.h | 32 ++++++++++-
.../exprs/aggregate/aggregate_function_array_agg.h | 2 +-
be/src/exprs/aggregate/aggregate_function_binary.h | 2 +-
.../exprs/aggregate/aggregate_function_collect.h | 2 +-
be/src/exprs/aggregate/aggregate_function_covar.h | 2 +-
.../exprs/aggregate/aggregate_function_distinct.h | 2 +-
.../exprs/aggregate/aggregate_function_foreach.h | 3 +-
.../aggregate/aggregate_function_foreachv2.cpp | 2 +-
.../aggregate_function_group_array_set_op.h | 2 +-
.../aggregate/aggregate_function_hll_union_agg.h | 2 +-
.../aggregate/aggregate_function_percentile.h | 63 ++++++++++++----------
.../exprs/aggregate/aggregate_function_retention.h | 2 +-
be/src/exprs/aggregate/aggregate_function_sort.h | 2 +-
.../aggregate/aggregate_function_state_union.h | 3 +-
.../exprs/aggregate/aggregate_function_statistic.h | 2 +-
be/src/exprs/aggregate/aggregate_function_stddev.h | 2 +-
be/src/exprs/aggregate/aggregate_function_topn.h | 26 ++++-----
.../aggregate/aggregate_function_window_funnel.h | 2 +-
.../aggregate_function_window_funnel_v2.h | 2 +-
19 files changed, 96 insertions(+), 59 deletions(-)
diff --git a/be/src/exprs/aggregate/aggregate_function.h b/be/src/exprs/aggregate/aggregate_function.h
index acc856056b0..da536f26ab1 100644
--- a/be/src/exprs/aggregate/aggregate_function.h
+++ b/be/src/exprs/aggregate/aggregate_function.h
@@ -303,12 +303,42 @@ protected:
int version {};
};
+/// Marker base for aggregate function classes that intentionally form an inheritance
+/// hierarchy (e.g. AggregateStateUnion -> AggregateStateMerge, or
+/// AggregateFunctionForEach -> AggregateFunctionForEachV2) and therefore cannot be
+/// marked 'final'. Classes that inherit this marker are exempt from the
+/// static_assert in IAggregateFunctionHelper.
+struct AggregateFunctionNonFinalBase {};
+
/// Implement method to obtain an address of 'add' function.
template <typename Derived>
class IAggregateFunctionHelper : public IAggregateFunction {
public:
IAggregateFunctionHelper(const DataTypes& argument_types_)
- : IAggregateFunction(argument_types_) {}
+ : IAggregateFunction(argument_types_) {
+ // NOTE: This static_assert is placed in the constructor body (not at class scope)
+ // because at class-scope instantiation time Derived is still an incomplete type,
+ // whereas the constructor body is instantiated lazily when a concrete object is
+ // constructed, at which point Derived is fully defined.
+ //
+ // Marking Derived as 'final' is an *optimization hint*, not a correctness
+ // requirement. add() is virtual in IAggregateFunction, so subclasses always
+ // dispatch correctly through the vtable regardless. However, when Derived is
+ // final, the compiler can see that assert_cast<const Derived*>(this)->add(...)
+ // inside add_batch() / add_batch_single_place() etc. has no further overrides,
+ // allowing it to devirtualize (and potentially inline) the add() call -- which
+ // is critical for hot aggregation paths.
+ //
+ // Classes that intentionally form inheritance hierarchies (and therefore accept
+ // the vtable overhead) must inherit AggregateFunctionNonFinalBase to opt out.
+ static_assert(
+ std::is_final_v<Derived> ||
+ std::is_base_of_v<AggregateFunctionNonFinalBase, Derived>,
+ "Derived should be marked 'final' to allow the compiler to devirtualize "
+ "add() calls inside add_batch() and related hot paths. "
+ "If the class intentionally has subclasses, inherit AggregateFunctionNonFinalBase "
+ "to opt out of this check.");
+ }
void destroy_vec(AggregateDataPtr __restrict place,
const size_t num_rows) const noexcept override {
diff --git a/be/src/exprs/aggregate/aggregate_function_array_agg.h b/be/src/exprs/aggregate/aggregate_function_array_agg.h
index e530cd34ae3..cf1dc2173a9 100644
--- a/be/src/exprs/aggregate/aggregate_function_array_agg.h
+++ b/be/src/exprs/aggregate/aggregate_function_array_agg.h
@@ -277,7 +277,7 @@ struct AggregateFunctionArrayAggData<T> {
//ShowNull is just used to support array_agg because array_agg needs to display NULL
//todo: Supports order by sorting for array_agg
template <typename Data>
-class AggregateFunctionArrayAgg
+class AggregateFunctionArrayAgg final
: public IAggregateFunctionDataHelper<Data, AggregateFunctionArrayAgg<Data>, true>,
UnaryExpression,
NotNullableAggregateFunction {
diff --git a/be/src/exprs/aggregate/aggregate_function_binary.h b/be/src/exprs/aggregate/aggregate_function_binary.h
index b3faca16e3f..d04bac39fd9 100644
--- a/be/src/exprs/aggregate/aggregate_function_binary.h
+++ b/be/src/exprs/aggregate/aggregate_function_binary.h
@@ -41,7 +41,7 @@ struct StatFunc {
};
template <typename StatFunc>
-struct AggregateFunctionBinary
+struct AggregateFunctionBinary final
: public IAggregateFunctionDataHelper<typename StatFunc::Data,
AggregateFunctionBinary<StatFunc>>,
MultiExpression,
diff --git a/be/src/exprs/aggregate/aggregate_function_collect.h b/be/src/exprs/aggregate/aggregate_function_collect.h
index 55cd19045c4..831c4f04f90 100644
--- a/be/src/exprs/aggregate/aggregate_function_collect.h
+++ b/be/src/exprs/aggregate/aggregate_function_collect.h
@@ -392,7 +392,7 @@ struct AggregateFunctionCollectListData<T, HasLimit> {
};
template <typename Data, bool HasLimit>
-class AggregateFunctionCollect
+class AggregateFunctionCollect final
: public IAggregateFunctionDataHelper<Data, AggregateFunctionCollect<Data, HasLimit>, true>,
VarargsExpression,
NotNullableAggregateFunction {
diff --git a/be/src/exprs/aggregate/aggregate_function_covar.h b/be/src/exprs/aggregate/aggregate_function_covar.h
index db3959c5f7a..e287dc060bd 100644
--- a/be/src/exprs/aggregate/aggregate_function_covar.h
+++ b/be/src/exprs/aggregate/aggregate_function_covar.h
@@ -137,7 +137,7 @@ struct SampData : BaseData<T> {
};
template <typename Data>
-class AggregateFunctionSampCovariance
+class AggregateFunctionSampCovariance final
: public IAggregateFunctionDataHelper<Data, AggregateFunctionSampCovariance<Data>>,
MultiExpression,
NullableAggregateFunction {
diff --git a/be/src/exprs/aggregate/aggregate_function_distinct.h b/be/src/exprs/aggregate/aggregate_function_distinct.h
index 8a9dde16f6b..060817188b2 100644
--- a/be/src/exprs/aggregate/aggregate_function_distinct.h
+++ b/be/src/exprs/aggregate/aggregate_function_distinct.h
@@ -260,7 +260,7 @@ struct AggregateFunctionDistinctMultipleGenericData
* Adding -Distinct suffix to aggregate function
**/
template <template <bool stable> typename Data, bool stable = false>
-class AggregateFunctionDistinct
+class AggregateFunctionDistinct final
: public IAggregateFunctionDataHelper<Data<stable>,
AggregateFunctionDistinct<Data, stable>>,
VarargsExpression,
diff --git a/be/src/exprs/aggregate/aggregate_function_foreach.h b/be/src/exprs/aggregate/aggregate_function_foreach.h
index faa86d8303b..8afd5b93eaa 100644
--- a/be/src/exprs/aggregate/aggregate_function_foreach.h
+++ b/be/src/exprs/aggregate/aggregate_function_foreach.h
@@ -51,7 +51,8 @@ struct AggregateFunctionForEachData {
*
* TODO Allow variable number of arguments.
*/
-class AggregateFunctionForEach : public IAggregateFunctionDataHelper<AggregateFunctionForEachData,
+class AggregateFunctionForEach : public AggregateFunctionNonFinalBase,
+ public IAggregateFunctionDataHelper<AggregateFunctionForEachData,
AggregateFunctionForEach>,
VarargsExpression,
NullableAggregateFunction {
diff --git a/be/src/exprs/aggregate/aggregate_function_foreachv2.cpp b/be/src/exprs/aggregate/aggregate_function_foreachv2.cpp
index 11a5a5cfba2..d8f0eac327a 100644
--- a/be/src/exprs/aggregate/aggregate_function_foreachv2.cpp
+++ b/be/src/exprs/aggregate/aggregate_function_foreachv2.cpp
@@ -35,7 +35,7 @@ namespace doris {
// because we may have already assumed that the array's elements are always nullable types, and many places have such checks.
// V1 code is kept to ensure compatibility during upgrades and downgrades.
// V2 code differs from V1 only in the return type and insert_into logic; all other logic is exactly the same.
-class AggregateFunctionForEachV2 : public AggregateFunctionForEach {
+class AggregateFunctionForEachV2 final : public AggregateFunctionForEach {
public:
constexpr static auto AGG_FOREACH_SUFFIX = "_foreachv2";
AggregateFunctionForEachV2(AggregateFunctionPtr nested_function_, const DataTypes& arguments)
diff --git a/be/src/exprs/aggregate/aggregate_function_group_array_set_op.h b/be/src/exprs/aggregate/aggregate_function_group_array_set_op.h
index f1b03402260..2eafcc337ab 100644
--- a/be/src/exprs/aggregate/aggregate_function_group_array_set_op.h
+++ b/be/src/exprs/aggregate/aggregate_function_group_array_set_op.h
@@ -405,7 +405,7 @@ struct GroupArrayStringUnionData : public GroupArraySetOpStringBaseData {
/// Puts all values to the hybrid set. Returns an array of unique values
template <typename ImplData>
-class AggregateFunctionGroupArraySetOp
+class AggregateFunctionGroupArraySetOp final
: public IAggregateFunctionDataHelper<ImplData, AggregateFunctionGroupArraySetOp<ImplData>>,
UnaryExpression,
NotNullableAggregateFunction {
diff --git a/be/src/exprs/aggregate/aggregate_function_hll_union_agg.h b/be/src/exprs/aggregate/aggregate_function_hll_union_agg.h
index cd729422b90..5b45221e66a 100644
--- a/be/src/exprs/aggregate/aggregate_function_hll_union_agg.h
+++ b/be/src/exprs/aggregate/aggregate_function_hll_union_agg.h
@@ -100,7 +100,7 @@ struct AggregateFunctionHLLUnionAggImpl : Data {
};
template <typename Data>
-class AggregateFunctionHLLUnion
+class AggregateFunctionHLLUnion final
: public IAggregateFunctionDataHelper<Data, AggregateFunctionHLLUnion<Data>>,
UnaryExpression,
NullableAggregateFunction {
diff --git a/be/src/exprs/aggregate/aggregate_function_percentile.h b/be/src/exprs/aggregate/aggregate_function_percentile.h
index 32423b4f87b..6a917460ffd 100644
--- a/be/src/exprs/aggregate/aggregate_function_percentile.h
+++ b/be/src/exprs/aggregate/aggregate_function_percentile.h
@@ -154,42 +154,40 @@ struct PercentileApproxState {
float compressions = 10000;
};
-class AggregateFunctionPercentileApprox
- : public IAggregateFunctionDataHelper<PercentileApproxState,
- AggregateFunctionPercentileApprox> {
+template <typename Derived>
+class AggregateFunctionPercentileApproxBase
+ : public IAggregateFunctionDataHelper<PercentileApproxState, Derived> {
public:
- AggregateFunctionPercentileApprox(const DataTypes& argument_types_)
- : IAggregateFunctionDataHelper<PercentileApproxState,
- AggregateFunctionPercentileApprox>(argument_types_) {}
+ AggregateFunctionPercentileApproxBase(const DataTypes& argument_types_)
+ : IAggregateFunctionDataHelper<PercentileApproxState, Derived>(argument_types_) {}
String get_name() const override { return "percentile_approx"; }
- void reset(AggregateDataPtr __restrict place) const override {
- AggregateFunctionPercentileApprox::data(place).reset();
- }
+ void reset(AggregateDataPtr __restrict place) const override { this->data(place).reset(); }
void merge(AggregateDataPtr __restrict place, ConstAggregateDataPtr rhs,
Arena&) const override {
- AggregateFunctionPercentileApprox::data(place).merge(
- AggregateFunctionPercentileApprox::data(rhs));
+ this->data(place).merge(this->data(rhs));
}
void serialize(ConstAggregateDataPtr __restrict place, BufferWritable& buf) const override {
- AggregateFunctionPercentileApprox::data(place).write(buf);
+ this->data(place).write(buf);
}
void deserialize(AggregateDataPtr __restrict place, BufferReadable& buf,
Arena&) const override {
- AggregateFunctionPercentileApprox::data(place).read(buf);
+ this->data(place).read(buf);
}
};
-class AggregateFunctionPercentileApproxTwoParams final : public AggregateFunctionPercentileApprox,
- public MultiExpression,
- public NullableAggregateFunction {
+class AggregateFunctionPercentileApproxTwoParams final
+ : public AggregateFunctionPercentileApproxBase<AggregateFunctionPercentileApproxTwoParams>,
+ public MultiExpression,
+ public NullableAggregateFunction {
public:
AggregateFunctionPercentileApproxTwoParams(const DataTypes& argument_types_)
- : AggregateFunctionPercentileApprox(argument_types_) {}
+ : AggregateFunctionPercentileApproxBase<AggregateFunctionPercentileApproxTwoParams>(
+ argument_types_) {}
void add(AggregateDataPtr __restrict place, const IColumn** columns, ssize_t row_num,
Arena&) const override {
const auto& sources =
@@ -204,7 +202,7 @@ public:
void insert_result_into(ConstAggregateDataPtr __restrict place, IColumn& to) const override {
auto& col = assert_cast<ColumnFloat64&>(to);
- double result = AggregateFunctionPercentileApprox::data(place).get();
+ double result = this->data(place).get();
if (std::isnan(result)) {
col.insert_default();
@@ -214,12 +212,15 @@ public:
}
};
-class AggregateFunctionPercentileApproxThreeParams final : public AggregateFunctionPercentileApprox,
- public MultiExpression,
- public NullableAggregateFunction {
+class AggregateFunctionPercentileApproxThreeParams final
+ : public AggregateFunctionPercentileApproxBase<
+ AggregateFunctionPercentileApproxThreeParams>,
+ public MultiExpression,
+ public NullableAggregateFunction {
public:
AggregateFunctionPercentileApproxThreeParams(const DataTypes& argument_types_)
- : AggregateFunctionPercentileApprox(argument_types_) {}
+ : AggregateFunctionPercentileApproxBase<AggregateFunctionPercentileApproxThreeParams>(
+ argument_types_) {}
void add(AggregateDataPtr __restrict place, const IColumn** columns, ssize_t row_num,
Arena&) const override {
const auto& sources =
@@ -238,7 +239,7 @@ public:
void insert_result_into(ConstAggregateDataPtr __restrict place, IColumn& to) const override {
auto& col = assert_cast<ColumnFloat64&>(to);
- double result = AggregateFunctionPercentileApprox::data(place).get();
+ double result = this->data(place).get();
if (std::isnan(result)) {
col.insert_default();
@@ -249,12 +250,14 @@ public:
};
class AggregateFunctionPercentileApproxWeightedThreeParams final
- : public AggregateFunctionPercentileApprox,
+ : public AggregateFunctionPercentileApproxBase<
+ AggregateFunctionPercentileApproxWeightedThreeParams>,
MultiExpression,
NullableAggregateFunction {
public:
AggregateFunctionPercentileApproxWeightedThreeParams(const DataTypes& argument_types_)
- : AggregateFunctionPercentileApprox(argument_types_) {}
+ : AggregateFunctionPercentileApproxBase<
+ AggregateFunctionPercentileApproxWeightedThreeParams>(argument_types_) {}
void add(AggregateDataPtr __restrict place, const IColumn** columns, ssize_t row_num,
Arena&) const override {
@@ -274,7 +277,7 @@ public:
void insert_result_into(ConstAggregateDataPtr __restrict place, IColumn& to) const override {
auto& col = assert_cast<ColumnFloat64&>(to);
- double result = AggregateFunctionPercentileApprox::data(place).get();
+ double result = this->data(place).get();
if (std::isnan(result)) {
col.insert_default();
@@ -285,12 +288,14 @@ public:
};
class AggregateFunctionPercentileApproxWeightedFourParams final
- : public AggregateFunctionPercentileApprox,
+ : public AggregateFunctionPercentileApproxBase<
+ AggregateFunctionPercentileApproxWeightedFourParams>,
MultiExpression,
NullableAggregateFunction {
public:
AggregateFunctionPercentileApproxWeightedFourParams(const DataTypes& argument_types_)
- : AggregateFunctionPercentileApprox(argument_types_) {}
+ : AggregateFunctionPercentileApproxBase<
+ AggregateFunctionPercentileApproxWeightedFourParams>(argument_types_) {}
void add(AggregateDataPtr __restrict place, const IColumn** columns, ssize_t row_num,
Arena&) const override {
const auto& sources =
@@ -312,7 +317,7 @@ public:
void insert_result_into(ConstAggregateDataPtr __restrict place, IColumn& to) const override {
auto& col = assert_cast<ColumnFloat64&>(to);
- double result = AggregateFunctionPercentileApprox::data(place).get();
+ double result = this->data(place).get();
if (std::isnan(result)) {
col.insert_default();
diff --git a/be/src/exprs/aggregate/aggregate_function_retention.h b/be/src/exprs/aggregate/aggregate_function_retention.h
index bcd5a5b5b96..ad6181d5ddb 100644
--- a/be/src/exprs/aggregate/aggregate_function_retention.h
+++ b/be/src/exprs/aggregate/aggregate_function_retention.h
@@ -105,7 +105,7 @@ struct RetentionState {
}
};
-class AggregateFunctionRetention
+class AggregateFunctionRetention final
: public IAggregateFunctionDataHelper<RetentionState, AggregateFunctionRetention>,
VarargsExpression,
NullableAggregateFunction {
diff --git a/be/src/exprs/aggregate/aggregate_function_sort.h b/be/src/exprs/aggregate/aggregate_function_sort.h
index c0a42ef4b9e..e001cb0c4c4 100644
--- a/be/src/exprs/aggregate/aggregate_function_sort.h
+++ b/be/src/exprs/aggregate/aggregate_function_sort.h
@@ -114,7 +114,7 @@ struct AggregateFunctionSortData {
};
template <typename Data>
-class AggregateFunctionSort
+class AggregateFunctionSort final
: public IAggregateFunctionDataHelper<Data, AggregateFunctionSort<Data>> {
private:
static constexpr auto prefix_size = sizeof(Data);
diff --git a/be/src/exprs/aggregate/aggregate_function_state_union.h b/be/src/exprs/aggregate/aggregate_function_state_union.h
index 9569db98398..1c8242bf53f 100644
--- a/be/src/exprs/aggregate/aggregate_function_state_union.h
+++ b/be/src/exprs/aggregate/aggregate_function_state_union.h
@@ -25,7 +25,8 @@
namespace doris {
const static std::string AGG_UNION_SUFFIX = "_union";
-class AggregateStateUnion : public IAggregateFunctionHelper<AggregateStateUnion> {
+class AggregateStateUnion : public AggregateFunctionNonFinalBase,
+ public IAggregateFunctionHelper<AggregateStateUnion> {
public:
AggregateStateUnion(AggregateFunctionPtr function, const DataTypes& argument_types_,
DataTypePtr return_type)
diff --git a/be/src/exprs/aggregate/aggregate_function_statistic.h b/be/src/exprs/aggregate/aggregate_function_statistic.h
index e90978b1f99..56e92ebf65f 100644
--- a/be/src/exprs/aggregate/aggregate_function_statistic.h
+++ b/be/src/exprs/aggregate/aggregate_function_statistic.h
@@ -55,7 +55,7 @@ struct StatFuncOneArg {
};
template <typename StatFunc, bool NullableInput>
-class AggregateFunctionVarianceSimple
+class AggregateFunctionVarianceSimple final
: public IAggregateFunctionDataHelper<
typename StatFunc::Data,
AggregateFunctionVarianceSimple<StatFunc, NullableInput>> {
diff --git a/be/src/exprs/aggregate/aggregate_function_stddev.h b/be/src/exprs/aggregate/aggregate_function_stddev.h
index 476744fde1d..a870b4695ff 100644
--- a/be/src/exprs/aggregate/aggregate_function_stddev.h
+++ b/be/src/exprs/aggregate/aggregate_function_stddev.h
@@ -175,7 +175,7 @@ struct StddevSampName {
};
template <typename Data>
-class AggregateFunctionSampVariance
+class AggregateFunctionSampVariance final
: public IAggregateFunctionDataHelper<Data, AggregateFunctionSampVariance<Data>>,
UnaryExpression,
NullableAggregateFunction {
diff --git a/be/src/exprs/aggregate/aggregate_function_topn.h b/be/src/exprs/aggregate/aggregate_function_topn.h
index d887950cd09..0787a936e87 100644
--- a/be/src/exprs/aggregate/aggregate_function_topn.h
+++ b/be/src/exprs/aggregate/aggregate_function_topn.h
@@ -296,14 +296,12 @@ struct AggregateFunctionTopNImplWeight {
};
//base function
-template <typename Impl>
+template <typename Impl, typename Derived>
class AggregateFunctionTopNBase
- : public IAggregateFunctionDataHelper<typename Impl::Data,
- AggregateFunctionTopNBase<Impl>> {
+ : public IAggregateFunctionDataHelper<typename Impl::Data, Derived> {
public:
AggregateFunctionTopNBase(const DataTypes& argument_types_)
- : IAggregateFunctionDataHelper<typename Impl::Data, AggregateFunctionTopNBase<Impl>>(
- argument_types_) {}
+ : IAggregateFunctionDataHelper<typename Impl::Data, Derived>(argument_types_) {}
void add(AggregateDataPtr __restrict place, const IColumn** columns, ssize_t row_num,
Arena&) const override {
@@ -329,12 +327,13 @@ public:
//topn function return string
template <typename Impl>
-class AggregateFunctionTopN final : public AggregateFunctionTopNBase<Impl>,
- MultiExpression,
- NullableAggregateFunction {
+class AggregateFunctionTopN final
+ : public AggregateFunctionTopNBase<Impl, AggregateFunctionTopN<Impl>>,
+ MultiExpression,
+ NullableAggregateFunction {
public:
AggregateFunctionTopN(const DataTypes& argument_types_)
- : AggregateFunctionTopNBase<Impl>(argument_types_) {}
+ : AggregateFunctionTopNBase<Impl, AggregateFunctionTopN<Impl>>(argument_types_) {}
String get_name() const override { return "topn"; }
@@ -348,12 +347,13 @@ public:
//topn function return array
template <typename Impl>
-class AggregateFunctionTopNArray final : public AggregateFunctionTopNBase<Impl>,
- MultiExpression,
- NullableAggregateFunction {
+class AggregateFunctionTopNArray final
+ : public AggregateFunctionTopNBase<Impl, AggregateFunctionTopNArray<Impl>>,
+ MultiExpression,
+ NullableAggregateFunction {
public:
AggregateFunctionTopNArray(const DataTypes& argument_types_)
- : AggregateFunctionTopNBase<Impl>(argument_types_),
+ : AggregateFunctionTopNBase<Impl, AggregateFunctionTopNArray<Impl>>(argument_types_),
_argument_type(argument_types_[0]) {}
String get_name() const override { return Impl::get_name(); }
diff --git a/be/src/exprs/aggregate/aggregate_function_window_funnel.h b/be/src/exprs/aggregate/aggregate_function_window_funnel.h
index 69f81fdcb47..859a91c8451 100644
--- a/be/src/exprs/aggregate/aggregate_function_window_funnel.h
+++ b/be/src/exprs/aggregate/aggregate_function_window_funnel.h
@@ -341,7 +341,7 @@ struct WindowFunnelState {
}
};
-class AggregateFunctionWindowFunnel
+class AggregateFunctionWindowFunnel final
: public IAggregateFunctionDataHelper<WindowFunnelState, AggregateFunctionWindowFunnel>,
MultiExpression,
NullableAggregateFunction {
diff --git a/be/src/exprs/aggregate/aggregate_function_window_funnel_v2.h b/be/src/exprs/aggregate/aggregate_function_window_funnel_v2.h
index 759890f6f9e..fb0a72363b0 100644
--- a/be/src/exprs/aggregate/aggregate_function_window_funnel_v2.h
+++ b/be/src/exprs/aggregate/aggregate_function_window_funnel_v2.h
@@ -616,7 +616,7 @@ private:
}
};
-class AggregateFunctionWindowFunnelV2
+class AggregateFunctionWindowFunnelV2 final
: public IAggregateFunctionDataHelper<WindowFunnelStateV2, AggregateFunctionWindowFunnelV2>,
MultiExpression,
NullableAggregateFunction {
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org