Hen*_*enk 5 c++ gcc sfinae implicit-conversion
我想要一个代表具有某种维度的单位的类。这应该表示 1.5m^2 之类的东西。应允许与某种类型进行标量乘法,并且无量纲单位的行为应与基础类型完全相同。这是我的解决方案:
#include <type_traits>
template<typename T, int Dim>
class Unit {
    public:
    explicit Unit(T t): _value(t) {}
    template<int D = Dim, typename std::enable_if_t<D==0, int> = 0>
    operator T() { static_assert(Dim==0, ""); return _value; } //static_assert not necessary, but gives error if template is removed
    T _value;
};
template<typename S, typename T, int Dim>
auto operator*(S s, Unit<T,Dim> unit)
{
    return Unit<T, Dim>(s * unit._value);
}
auto main() -> int
{
    auto i = double{0};
//Scalar test
    auto scalar = int{0};
    auto x = Unit<double,1>(i);
    auto test = scalar * x;
//Conversion test
    auto y = Unit<double,0>(i);
    return y + i;
}
这在 clang 中工作得很好(https://godbolt.org/z/8Pev7W6Y1)。但是,由于模板化转换运算符(转换运算符:gcc vs clang)的 GCC 错误,这在 GCC 中不起作用。
不可能删除 SFINAE 结构,因为它(正确地)遇到了static_assert.
您是否有在 GCC 中也能运行的等效代码的想法?该代码应该可以在 C++17 中使用两种编译器运行。
您可以使用专业化代替 SFINAE。为了避免太多重复,您可以将公共部分(任何不依赖于 的部分Dim)移至基类:
#include <type_traits>
template <typename T>
class base_unit {
    public:
    explicit base_unit(T t): _value(t) {}
    T _value;
};
template<typename T, int Dim>
class Unit : public base_unit<T> {
public:
    explicit Unit(T t): base_unit<T>(t) {}
};
template <typename T>
class Unit<T,0> : public base_unit<T> {
public:
    explicit Unit(T t) : base_unit<T>(t) {}
    operator T() { return base_unit<T>::_value; }
};
template<typename S, typename T, int Dim>
auto operator*(S s, Unit<T,Dim> unit)
{
    return Unit<T, Dim>(s * unit._value);
}
auto main() -> int
{
    auto i = double{0};
//Scalar test
    auto scalar = int{0};
    auto x = Unit<double,1>(i);
    auto test = scalar * x;
//Conversion test
    auto y = Unit<double,0>(i);
    return y + i;
}
请注意,这有点过时,并且没有考虑更现代的 C++20 方法(例如operator T() requires (Dim == 0)评论中提到的方法)。
| 归档时间: | 
 | 
| 查看次数: | 105 次 | 
| 最近记录: |