【发布时间】:2022-01-07 05:21:12
【问题描述】:
我想要一个代表具有某种维度的单元的类。这应该表示 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) 中运行良好。但是,由于模板化转换运算符 (Conversion operator: gcc vs clang) 的 GCC 错误,这在 GCC 中不起作用。
无法删除 SFINAE 构造,因为它(正确地)运行到 static_assert。
您对在 GCC 中也适用的等效代码有什么想法吗?代码应该在 C++17 中与两个编译器一起工作。
【问题讨论】:
-
您能否展示一个您想要编译的代码示例,但如果模板被删除,它会无法编译?如果我从 Godbolt 链接中删除模板,gcc 和 clang 都会编译链接中的代码
-
在 C++20 中,
operator T() requires (Dim == 0)可以完成 Demo 的工作。 -
@NathanOliver:我认为恰恰相反,
static_cast<double>(Unit<double,2>(0))在没有 SFINAE(和static_assert)的情况下会错误编译 -
@Jarod42 我明白了,但是如果他们保留静态断言,它仍然无法编译。我试图理解无法删除 SFINAE 构造,因为它(正确地)运行到了 static_assert。我不确定这是什么意思
-
你说得对,我搞砸了最小的例子(并且失败并检查)。我的真实示例中的问题是转换运算符在给定的
operator*之前尝试,然后运行到static_assert。我正在尝试修复示例。
标签: c++ gcc implicit-conversion sfinae