无法从 initializer_list 转换为我的类型,该类型具有模板化可变参数构造函数
Cannot convert from initializer_list to my type, which has templated variadic constructor
所以,这并不是我 必须 做的事情,我只是在玩。我为任何数字类型和任意数量的坐标的向量写了一个 Vector
class 。它用作 Vector<NumericType, [num of coords]>
。这是代码:
#include <array>
#include <functional>
namespace World {
template <typename NumType, unsigned char Size>
class Vector
{
public:
using CoordType = NumType;
template<typename... NumTypes>
constexpr Vector(NumTypes&&... vals) : values{ std::forward<NumTypes>(vals)... }
{
static_assert(sizeof...(NumTypes) == Size, "You must provide N arguments.");
}
Vector(const std::array<NumType, Size>& values) : values(values) {}
Vector(const std::array<NumType, Size>&& values) : values(std::move(values)) {}
const NumType& operator[](size_t offset) const { return values[offset]; }
NumType& operator[](size_t offset) { return values[offset]; }
//! Converts all values to new given type
template <typename NewType>
constexpr Vector<NewType, Size> Convert() const { return Convert<NewType>(std::make_index_sequence<Size>{}); }
//! Converts all values via the conversion function
template <typename NewType>
Vector<NewType, Size> Convert(const std::function<NewType(NumType)>& callback) const { return Convert<NewType>(std::make_index_sequence<Size>{}, callback); }
std::array<NumType, Size> values;
private:
//! Converts all values to new given type
template <typename NewType, std::size_t ... Is>
constexpr Vector<NewType, Size> Convert(std::index_sequence<Is...>) const { return { { static_cast<NewType>(values[Is])}... }; }
//! Converts all values via the conversion function
template <typename NewType, std::size_t ... Is>
Vector<NewType, Size> Convert(std::index_sequence<Is...>, const std::function<NewType(NumType)>& callback) const { return { { callback(values[Is])}... } ; }
};
现在我要做的是确保上面声明的转换函数正常工作。使用思路是这样的:
using namespace World;
using Vector3D = Vector<double, 3>;
using Vector3Int = Vector<int, 3>;
#include <cmath>
int main()
{
const Vector3D src{ 1.4, 2.5, 3.6 };
const Vector3Int target = src.Convert<int>([](double val) { return (int)std::round(val); });
return 0;
}
这里的问题是编译转换函数时,生成的新值以std::initializer_list<NewType>
的形式出现。出于某种原因,这不符合构造函数 Vector(NumTypes&&... vals)
的条件。现在我不想有一个初始化列表构造函数 - 预期参数的数量不是可变的,它必须是 Size
模板参数所说的任何内容。
那么如何解决这个问题呢?我怎样才能将 std::initializer_list
转换为 NumTypes&&... vals
是什么?
我必须承认,我并不确切地知道我在做什么,我正在努力提高我的 C++ 知识。
在 Convert
中,您有参数包 Is
,您希望将其与 callback
和 values
结合使用。
参数包扩展“扩展为以逗号分隔的零个或多个模式列表”,因此当与问题中的值一起使用时,您将得到:
Is...
0, 1, 2
values[Is]...
=> values[0], values[1], values[2]
1.4, 2.5, 3.6
callback(values[Is])...
=> callback(values[0]), callback(values[1]), callback(values[2])
1, 3, 4
并且您想像这样创建一个 braced-init-list:
{callback(values[0]), callback(values[1]), callback(values[2])}
// =>
{1, 3, 4}
所以:
template <typename NewType, std::size_t... Is>
Vector<NewType, Size>
Convert(std::index_sequence<Is...>,
const std::function<NewType(NumType)>& callback) const
{
return {callback(values[Is])...};
}
所以,这并不是我 必须 做的事情,我只是在玩。我为任何数字类型和任意数量的坐标的向量写了一个 Vector
class 。它用作 Vector<NumericType, [num of coords]>
。这是代码:
#include <array>
#include <functional>
namespace World {
template <typename NumType, unsigned char Size>
class Vector
{
public:
using CoordType = NumType;
template<typename... NumTypes>
constexpr Vector(NumTypes&&... vals) : values{ std::forward<NumTypes>(vals)... }
{
static_assert(sizeof...(NumTypes) == Size, "You must provide N arguments.");
}
Vector(const std::array<NumType, Size>& values) : values(values) {}
Vector(const std::array<NumType, Size>&& values) : values(std::move(values)) {}
const NumType& operator[](size_t offset) const { return values[offset]; }
NumType& operator[](size_t offset) { return values[offset]; }
//! Converts all values to new given type
template <typename NewType>
constexpr Vector<NewType, Size> Convert() const { return Convert<NewType>(std::make_index_sequence<Size>{}); }
//! Converts all values via the conversion function
template <typename NewType>
Vector<NewType, Size> Convert(const std::function<NewType(NumType)>& callback) const { return Convert<NewType>(std::make_index_sequence<Size>{}, callback); }
std::array<NumType, Size> values;
private:
//! Converts all values to new given type
template <typename NewType, std::size_t ... Is>
constexpr Vector<NewType, Size> Convert(std::index_sequence<Is...>) const { return { { static_cast<NewType>(values[Is])}... }; }
//! Converts all values via the conversion function
template <typename NewType, std::size_t ... Is>
Vector<NewType, Size> Convert(std::index_sequence<Is...>, const std::function<NewType(NumType)>& callback) const { return { { callback(values[Is])}... } ; }
};
现在我要做的是确保上面声明的转换函数正常工作。使用思路是这样的:
using namespace World;
using Vector3D = Vector<double, 3>;
using Vector3Int = Vector<int, 3>;
#include <cmath>
int main()
{
const Vector3D src{ 1.4, 2.5, 3.6 };
const Vector3Int target = src.Convert<int>([](double val) { return (int)std::round(val); });
return 0;
}
这里的问题是编译转换函数时,生成的新值以std::initializer_list<NewType>
的形式出现。出于某种原因,这不符合构造函数 Vector(NumTypes&&... vals)
的条件。现在我不想有一个初始化列表构造函数 - 预期参数的数量不是可变的,它必须是 Size
模板参数所说的任何内容。
那么如何解决这个问题呢?我怎样才能将 std::initializer_list
转换为 NumTypes&&... vals
是什么?
我必须承认,我并不确切地知道我在做什么,我正在努力提高我的 C++ 知识。
在 Convert
中,您有参数包 Is
,您希望将其与 callback
和 values
结合使用。
参数包扩展“扩展为以逗号分隔的零个或多个模式列表”,因此当与问题中的值一起使用时,您将得到:
Is...
0, 1, 2
values[Is]...
=> values[0], values[1], values[2]
1.4, 2.5, 3.6
callback(values[Is])...
=> callback(values[0]), callback(values[1]), callback(values[2])
1, 3, 4
并且您想像这样创建一个 braced-init-list:
{callback(values[0]), callback(values[1]), callback(values[2])}
// =>
{1, 3, 4}
所以:
template <typename NewType, std::size_t... Is>
Vector<NewType, Size>
Convert(std::index_sequence<Is...>,
const std::function<NewType(NumType)>& callback) const
{
return {callback(values[Is])...};
}