有没有办法从double隐式转换为std :: array <double,1>?

时间:2019-02-07 14:56:11

标签: c++ implicit-conversion stdarray

我有一个像这样的模板类:

template<int dimension>
class Foo{
  Foo(std::array<double, dimension>);
}

和一个函数

func(Foo<1> f);

我希望能够这样调用函数和构造函数:

func(1);
Foo<1> f(1);

代替

func({1});
Foo<1> f({1});

有没有很好的方法来实现这一目标?

如果无法进行隐式转换,则只能为Foo<1>情况添加一个构造函数吗?

5 个答案:

答案 0 :(得分:8)

无法将double隐式转换为std::array<double, 1>。这将需要重载double的转换运算符,但这无法完成,因为您无法重载内置类型的运算符。

您可以做的就是添加

Foo(double);

构造函数,然后使用static_assert之类的

static_assert(dimension == 1, "single double constructor only works if dimension == 1");
构造函数主体中的

,以使其仅在数组大小为1时才起作用。 (我喜欢使用static_assert,因为它可以让您编写漂亮的,描述性的错误消息)


您应该考虑将dimension重命名为size,因为这是数组中指定的内容。

答案 1 :(得分:5)

您可以为构造函数定义另一个重载,然后使用委托,例如像这样:

template<int dimension>
class Foo{
  public:
    Foo(std::array<double, dimension>) {}
    Foo(double init) : Foo(std::array<double, dimension>{{init}}) {}
};

这样,两个都需要调用

func(1);
Foo<1> f(1);

将起作用。

答案 2 :(得分:2)

一种稍微不同的方法是将可变参数模板用于构造函数。相对于其他解决方案,优点是您的类不拥有会导致编译错误的构造函数(通过意外地为尺寸大于1的Foo调用单双精度构造函数)。

template <int dimension>
class Foo {
 public:
  Foo(std::array<double, dimension>) {}

  template <typename... Is>
  Foo(Is... inits) : Foo{std::array<double, sizeof...(Is)>{inits...}} {}
};

Foo<1> f1(1.);
Foo<2> f2(1., 2.);

缺点是使用std::array时必须显式调用构造函数。

答案 3 :(得分:0)

还有另一个版本直接转发到您的存储变量。

template <int dimension>
class Foo {
public:
    std::array<double, dimension> data;

    template< class... Args >
    Foo(Args&&... args) : data{std::forward<Args>(args)...} {}
};

Foo<1> one(1.);
Foo<2> two(1., 2.);
// Foo<2> three(1., 2., 3.); // error: too many initializers for

答案 4 :(得分:0)

类似这样的东西:

#include <array>
#include <iostream>
#include <type_traits>

template < int dimension >
struct Foo
{
  Foo(std::array< double, dimension > x)
  : store_(x)
  {
    std::cout << "array\n";
  }

  template < class... Args, std::enable_if_t< sizeof...(Args) == dimension > * = nullptr >
  Foo(Args &&... args)
  : store_ { { double(args)... } }
  {
    std::cout << "items\n";
  }

  std::array< double, dimension > store_;
};

template < class... Ts >
auto use(Ts &&...)
{
}

int main()
{
  auto f1 = Foo< 1 >(std::array< double, 1 > { 1.0 });
  auto f2 = Foo< 1 >(1.0);

  use(f1);
  use(f2);

  auto f4 = Foo< 3 >(std::array< double, 3 > { 1.0, 2.0, 3 });
  auto f3 = Foo< 3 >(1, 2, 3);
  use(f3, f4);
}