没有子类型的C++模板

C++ template without subtype

本文关键字:C++ 模板 类型      更新时间:2023-10-16

我有类似的东西

template<typename T, typename U = SOMETHING<T>> class A;

template<typename T> using B = A<T, SOMETHING_ELSE<T>>;

如何确定函数实例化中使用的是SOMETHING还是SOMETHING_ELSE,例如:

class A: {
template<typename V>
create_new(V v); // return an A only depending on SOMETHING or SOMETHING_ELSE,
  // e.G: if A is instantiated with T, SOMETHING<T> the return shall be A<V, SOMETHING<V> >,
  // but if it is SOMETHING_ELSE, the return shall be of type A<V, SOMETHING_ELSE<V> >
}

我知道可以使用模板专业化,但有没有一种"更漂亮"的方法,在添加更多SOMETHINGS时不必编写大量新的规范?

真实代码:

template<typename Type = long, typename Canceling_Type<Type> = fract::canceled<Type>>
class fraction; // there are different canceling types

所需的功能是

template<typename Other_Type, typename Other_Cancel_Type>
fraction<decltype(Type() + Other_Type()), WHAT_HERE> &operator+(const fraction<Other_Type,Other_Cancel_Type> &

cancel_types仅由一个静态函数组成,该函数取消(或不取消)一个分数(未取消与该示例类似)

template<typename Type>
class meng::math::fract::canceled {
public:
  typedef fraction<Type,canceled<Type>> cancel_type;
  static cancel_type &cancel(cancel_type& to_cancel);
};

我的想法是从f中创建一个分数,这样就不会丢失精度(例如,类型int和long创建long的分数),但是具有由两个部分确定的取消类型(e.G。两个被取消的收益率都被取消了,混合收益率都没有被取消,例如,只有setter函数的行为被改变了,但它们是相同的数学概念,因此可以一起计算)

(英语不是我的第一语言,因此我希望取消分数意味着使用尽可能小的分子和分母)

如果我了解你的想法,你可以专门化某种特质。

namespace detail
{
  template<class T, class U, class CancelT, class CancelU>
  struct cancelor
  {
    using type = fract::uncanceled<std::common_type_t<T, U>>;
  };
  template<class T, class U>
  struct cancelor<T, U, fract::canceled<T>, fract::canceled<U>>
  {
    using type = fract::canceled<std::common_type_t<T, U>>;
  };
  template<class T, class U, class CancelT, class CancelU>
  using cancel_t = typename cancelor<T, U, CancelT, CancelU>::type;
}
template<class T, class CancelT = fract::canceled<T>>
struct X
{
  template<class U, class CancelU>
  X<std::common_type_t<T, U>, detail::cancel_t<T, U, CancelT, CancelU>> 
    operator+(X<U, CancelU> const & v) 
  { 
    using V = std::common_type_t<T, U>;
    using C = detail::cancel_t<T, U, CancelT, CancelU>;
    auto ret = X<V, C>{/*...*/};
    // do stuff with ret
    return ret;
  }
};

然后添加它们:

X<int, fract::canceled<int>> ci;
X<int, fract::uncanceled<int>> ui;
X<long, fract::canceled<long>> cl;
X<long, fract::uncanceled<long>> ul;
auto c = ci + cl;
auto u = ui + ul;
auto cu = ci + ul;
auto uc = ui + cl;
std::cout << type_name<decltype(c)>() << "n";
std::cout << type_name<decltype(u)>() << "n";
std::cout << type_name<decltype(cu)>() << "n";
std::cout << type_name<decltype(uc)>() << "n";

其中输出为:

struct X<long,struct fract::canceled<long>>
struct X<long,struct fract::uncanceled<long>>
struct X<long,struct fract::uncanceled<long>>
struct X<long,struct fract::uncanceled<long>>