Templates 如何在构造函数中应用算术类型提升

Templates 如何在构造函数中应用算术类型提升,templates,constructor,c++17,template-argument-deduction,type-promotion,Templates,Constructor,C++17,Template Argument Deduction,Type Promotion,假设,如果我正在创建一个point类,并且我希望它根据参数推断出类型,那么我希望它将point类提升到最高参数。例如: template <class dtype> class Point; ... auto x = Point(1, 1.0); // Point<double> specialized auto y = Point(1.0, 1); // Point<double> specialized 我不知道如何在构造函数中实现这一点。我已经能够

假设,如果我正在创建一个point类,并且我希望它根据参数推断出类型,那么我希望它将point类提升到最高参数。例如:

template <class dtype>
class Point;

...

auto x = Point(1, 1.0); // Point<double> specialized
auto y = Point(1.0, 1); // Point<double> specialized
我不知道如何在构造函数中实现这一点。我已经能够让它从调用显式专用构造函数的函数中推断出类型,但不能从构造函数本身推断出类型

以下是我迄今为止的尝试:

#include <type_traits>

template <typename... Ts>
struct promoted_type_wrap;

template <typename T>
struct promoted_type_wrap<T> {
  using type = T;
};

template <typename T, typename U, typename... Ts>
struct promoted_type_wrap<T, U, Ts...> {
  using type = typename promoted_type_wrap<typename std::conditional<
    (sizeof(U) <= sizeof(T)), T, U >::type, Ts... >::type;
};

template <typename... Ts>
using promoted_type = typename promoted_type_wrap<Ts...>::type;

template <typename T>
using same_type = typename promoted_type_wrap<T>::type;

template <class dtype>
class Point {
protected:
  dtype x, y;

public:
  constexpr Point(const dtype x, const same_type<dtype> y)
    : x(x), y(y) {
  }
};

template <class dtype, class etype>
constexpr auto make_Point(const dtype x, const etype y) {
  return Point<promoted_type<dtype, etype>>(x, y);
}

void test() {
  constexpr auto x = make_Point(1, 2.0); // Point<double> specialized
  constexpr auto y = make_Point(1.0, 2); // Point<double> specialized
  constexpr auto z = Point(1, 2.0); // Point<int> specialized
  constexpr auto w = Point(1.0, 2); // Point<double> specialized
}
这就解释了为什么Point1,2.0被专门化为一个点,因为第一个参数是一个int,它强制构造函数中的第二个参数为int;但是,我不确定如何重写构造函数,使其行为类似于伪构造函数工厂

但是,我不确定如何重写构造函数,使其行为类似于伪构造函数工厂

不是构造器:您必须编写自定义扣减指南

如下

template <typename T1, typename T2>
Point(T1, T2) -> Point<promoted_type<T1, T2>>;
#include <type_traits>

template <typename dtype>
class Point
 {
   protected:
      dtype x, y;

   public:
      template <typename T1, typename T2>
      constexpr Point (T1 const & a, T2 const & b) : x(a), y(b)
       { }
 };

template <typename T1, typename T2>
Point(T1, T2) -> Point<std::common_type_t<T1, T2>>;

int main ()
 {
   constexpr auto z = Point(1l, 2.0); // <-- deduced as Point<double>
   constexpr auto w = Point(1.0, 2l); // <-- deduced as Point<double>

   static_assert( std::is_same_v<decltype(z), Point<double> const> );
   static_assert( std::is_same_v<decltype(w), Point<double> const> );
 }
我建议使用一些独立于类型顺序选择首选类型的东西

在我看来,你应该使用以下方法

template <typename T1, typename T2>
Point(T1, T2) -> Point<promoted_type<T1, T2>>;
#include <type_traits>

template <typename dtype>
class Point
 {
   protected:
      dtype x, y;

   public:
      template <typename T1, typename T2>
      constexpr Point (T1 const & a, T2 const & b) : x(a), y(b)
       { }
 };

template <typename T1, typename T2>
Point(T1, T2) -> Point<std::common_type_t<T1, T2>>;

int main ()
 {
   constexpr auto z = Point(1l, 2.0); // <-- deduced as Point<double>
   constexpr auto w = Point(1.0, 2l); // <-- deduced as Point<double>

   static_assert( std::is_same_v<decltype(z), Point<double> const> );
   static_assert( std::is_same_v<decltype(w), Point<double> const> );
 }

关于使用普通类型的注意事项。我没有意识到它的存在。
#include <type_traits>

template <typename dtype>
class Point
 {
   protected:
      dtype x, y;

   public:
      template <typename T1, typename T2>
      constexpr Point (T1 const & a, T2 const & b) : x(a), y(b)
       { }
 };

template <typename T1, typename T2>
Point(T1, T2) -> Point<std::common_type_t<T1, T2>>;

int main ()
 {
   constexpr auto z = Point(1l, 2.0); // <-- deduced as Point<double>
   constexpr auto w = Point(1.0, 2l); // <-- deduced as Point<double>

   static_assert( std::is_same_v<decltype(z), Point<double> const> );
   static_assert( std::is_same_v<decltype(w), Point<double> const> );
 }