kphp
kphp copied to clipboard
Fix `VertexAdaptor` comparison
Some things about VertexAdaptor
:
- Comparison Operator Limitation: the comparison operator is defined only when there is a single template parameter.
- Template Friends: this class utilizes template friends classes to itself.
- Constructor/Assignment Operator Overloading: there is a constructor/assignment operator that takes the same class with a different template parameter.
- Cross-Instance Comparison and Implicit Conversions: when comparing two instances of the class with different template parameters, one instance is implicitly converted to the other. The intention is to use a hierarchy of casting defined by
op_type_is_base_of
. However, the static_assert does not establish the conversion algorithm, leading the compiler to consider that any class with any template parameter can be converted to the same class with any other template parameter. The intended behavior is to allow comparisons only between direct base classes (determined by theop_type_is_base_of
constexpr function). To achieve this, SFINAE with std::enable_if can be employed.
A small minimal reproducer of a problem is here:
#include <iostream>
enum Operation {
op_universal,
op_bin,
op_seq,
op_unary,
};
constexpr bool is_base_of(Operation a, Operation b) {
return a == op_universal;
}
template<Operation Op1>
class A {
int *impl_;
template<Operation Op2>
friend class A;
public:
// template<Operation FromOp, typename = std::enable_if_t<is_base_of(Op1, FromOp)>>
template<Operation FromOp>
A(const A<FromOp> &from) noexcept
: impl_(from.impl_) {
// before here was static assert is_base_of(Op1, FromOp)
}
// template<Operation FromOp, typename = std::enable_if_t<is_base_of(Op1, FromOp)>>
template<Operation FromOp>
A<Op1> &operator=(const A<FromOp> &from) noexcept {
// before here was static assert is_base_of(Op1, FromOp)
impl_ = from.impl_;
return *this;
}
explicit A(int * impl) : impl_(impl) {}
bool operator==(const A<Op1> &other) const noexcept {
return impl_ == other.impl_;
}
};
int main() {
A<op_seq> x(new int(32));
A<op_universal> y(new int(123));
if (x == y) {
std::cout << "Eq!\n";
}
}
With C++17 it's compilable using both clang and gcc.
But with C++20 it's compilable only with gcc.
This fix allows to compile kphp2cpp
target using C++20 and clang compiler.