C++ 标量和强制调用站点可读性?
我想知道目前推荐的通过利用类型系统消除参数歧义和提高函数调用站点可读性的方法是什么。一个简单的例子是C++ 标量和强制调用站点可读性?,c++,C++,我想知道目前推荐的通过利用类型系统消除参数歧义和提高函数调用站点可读性的方法是什么。一个简单的例子是 int total(int price, int amount) { return price * total; } 在这种情况下,很难准确地说出像total(10,2)这样的调用意味着什么,即哪个参数是哪个(在这种情况下,由于乘法的可交换性,如果弄乱了顺序,就不会出现错误) 基本上,您可以快速执行以下操作: enum class ScalarTypeTag { PriceTag, Amo
int total(int price, int amount) {
return price * total;
}
在这种情况下,很难准确地说出像total(10,2)
这样的调用意味着什么,即哪个参数是哪个(在这种情况下,由于乘法的可交换性,如果弄乱了顺序,就不会出现错误)
基本上,您可以快速执行以下操作:
enum class ScalarTypeTag { PriceTag, AmountTag, TotalTag};
template<typename T, ScalarTypeTag K>
struct ScalarWrapper {
explicit ScalarWrapper(T value) : value_{value} {}
T value_;
};
using Price = ScalarWrapper<int, ScalarTypeTag::PriceTag>;
using Amount = ScalarWrapper<int, ScalarTypeTag::PriceTag>;
using Total = ScalarWrapper<int, ScalarTypeTag::TotalTag>;
Total ComputeTotal(Price p, Amount n) {
return Total(p.value_ * n.value_);
}
enum类ScalarTypeTag{PriceTag,AmountTag,TotalTag};
模板
结构ScalarWrapper{
显式ScalarWrapper(T值):值{value}{}
T值;
};
使用Price=ScalarWrapper;
使用量=ScalarWrapper;
使用Total=ScalarWrapper;
计算总额(价格p,金额n){
返回总计(p.value×n.value);
}
这将使调用者很难混淆参数顺序,同时成为零成本抽象,因为编译器将优化包装类型。我基本上对如何做到这一点感兴趣,因此:
struct tag_t{constexpr tag_t(){};
struct tag_t {constexpr tag_t(){}};
inline constexpr tag_t price{}
inline constexpr tag_t amount{};
inline constexpr tag_t total{};
template<class T, tag_t const* tag>
struct scalar_t {
T t;
constexpr explicit scalar_t( T tin ):t(std::move(tin)) {}
constexpr scalar_t( scalar_t const& ) = default;
constexpr scalar_t( scalar_t && ) = default;
constexpr scalar_t& operator=( scalar_t const& ) = default;
constexpr scalar_t& operator=( scalar_t && ) = default;
constexpr scalar_t() = default;
constexpr ~scalar_t() = default;
};
template<auto x, tag_t const* tag >
constexpr auto scalar = scalar_t<std::decay_t<decltype(x)>, tag>(x);
template<tag_t const* tag>
using iscalar_t = scalar_t<int, tag>;
scalar_t<int, &total> ComputeTotal( scalar_t<int, &price> p, scalar_t<int, &amount> n ) {
return scalar_t<int, &total>( p.t * n.t );
}
内联constexpr标签价格{}
内联constexpr标记量{};
内联constexpr tag_t total{};
模板
结构标量{
T;
constexpr显式标量_t(t tin):t(std::move(tin)){
constexpr scalar\u t(scalar\u t const&)=默认值;
constexpr scalar_t(scalar_t&&)=默认值;
constexpr scalar\u t&operator=(scalar\u t const&)=默认值;
constexpr scalar_t&operator=(scalar_t&&)=默认值;
constexpr scalar_t()=默认值;
constexpr~scalar_t()=默认值;
};
模板
constexpr auto scalar=标量(x);
模板
使用iscalar\u t=标量\u t;
标量计算总数(标量p,标量n){
返回标量t(p.t*n.t);
}
打电话的人可以
int x = 33;
auto total = ComputeTotal( scalar<7, &price>, iscalar_t<&amount>( x ) );
intx=33;
自动总计=计算总计(标量,iscalar_t(x));
并使用强制转换传递编译时值或运行时值
我们不使用类型别名,而是为标记使用指向标记的指针。任何人都可以创建一个新的标量标记,它的constexpr地址就是它的标识
这允许分布式标量类型生成;
内联constexpr标签价格{}
内联constexpr标记量{};
内联constexpr tag_t total{};
模板
结构标量{
T;
constexpr显式标量_t(t tin):t(std::move(tin)){
constexpr scalar\u t(scalar\u t const&)=默认值;
constexpr scalar_t(scalar_t&&)=默认值;
constexpr scalar\u t&operator=(scalar\u t const&)=默认值;
constexpr scalar_t&operator=(scalar_t&&)=默认值;
constexpr scalar_t()=默认值;
constexpr~scalar_t()=默认值;
};
模板
constexpr auto scalar=标量(x);
模板
使用iscalar\u t=标量\u t;
标量计算总数(标量p,标量n){
返回标量t(p.t*n.t);
}
打电话的人可以
int x = 33;
auto total = ComputeTotal( scalar<7, &price>, iscalar_t<&amount>( x ) );
intx=33;
自动总计=计算总计(标量,iscalar_t(x));
并使用强制转换传递编译时值或运行时值
我们不使用类型别名,而是为标记使用指向标记的指针。任何人都可以创建一个新的标量标记,它的constexpr地址就是它的标识
这允许分布式标量类型生成。看起来这是的任务。看起来这是的任务。