有没有办法从 double 隐式转换为 std::array<double,1>?
Is there a way for implicit conversion from double to std::array<double,1>?
我有一个这样的模板class:
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});
有什么好的方法可以做到这一点吗?
如果隐式转换不可行,1 可以只为 Foo<1>
情况添加一个构造函数吗?
您可以为您的构造函数定义另一个重载,然后使用委托,例如像这样:
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);
会起作用。
无法将 double
隐式转换为 std::array<double, 1>
。这将需要为 double
重载转换运算符,但这无法完成,因为您不能为内置类型重载运算符。
你可以做的是添加
Foo(double);
构造函数然后使用static_assert
like
static_assert(dimension == 1, "single double constructor only works if dimension == 1");
在构造函数的主体中将其限制为仅在数组大小为 1
时才起作用。 (我喜欢尽可能使用 static_assert
,因为它可以让你写出漂亮的、描述性的错误消息)
您应该考虑将 dimension
重命名为 size
,因为这是数组中指定的内容。
一个略有不同的方法是为构造函数使用可变参数模板。与其他解决方案相比的优势在于,您的 class 没有可能导致编译错误的构造函数(通过不小心调用尺寸大于 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
时必须显式调用构造函数。
还有另一个版本直接转发到您的存储变量。
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
像这样:
#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);
}
我有一个这样的模板class:
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});
有什么好的方法可以做到这一点吗?
如果隐式转换不可行,1 可以只为 Foo<1>
情况添加一个构造函数吗?
您可以为您的构造函数定义另一个重载,然后使用委托,例如像这样:
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);
会起作用。
无法将 double
隐式转换为 std::array<double, 1>
。这将需要为 double
重载转换运算符,但这无法完成,因为您不能为内置类型重载运算符。
你可以做的是添加
Foo(double);
构造函数然后使用static_assert
like
static_assert(dimension == 1, "single double constructor only works if dimension == 1");
在构造函数的主体中将其限制为仅在数组大小为 1
时才起作用。 (我喜欢尽可能使用 static_assert
,因为它可以让你写出漂亮的、描述性的错误消息)
您应该考虑将 dimension
重命名为 size
,因为这是数组中指定的内容。
一个略有不同的方法是为构造函数使用可变参数模板。与其他解决方案相比的优势在于,您的 class 没有可能导致编译错误的构造函数(通过不小心调用尺寸大于 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
时必须显式调用构造函数。
还有另一个版本直接转发到您的存储变量。
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
像这样:
#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);
}