通过模板参数传递数据,C++
Pass data via template argument, C++
我正在考虑在我的程序中加入 color spaces 结构。现在你可以看到每种颜色 space 对其每个组件都有其限制。所以考虑这样的结构。
template<typename T>
struct SomeColorSpace{
T component1,component2,.....; // or std::array<T,N> components, N is compile-time const
};
现在我需要以某种方式定义一个范围,所以我创建了一个结构。
template<typename T>
struct Range{
T min, max;
// Some constructors initializing min and max...
};
现在我需要我的颜色 space 结构来了解其每个组件的范围。但如您所见,我不能只在我的结构中保留 std::array<Ranges<T>,N> ranges
,因为范围因类型而异。例如考虑 struct RGB
每个分量可能是 float
或 unsigned char
所以当分量是 float
时每个分量的范围变成 [0,1];
并且当它是无符号字符,它是 [0,255];
。为每种情况编写模板专业化是一种解决方案,但我想要这样的签名。 using RGBFloat = RGB<float,Range<float>...>
。我的意思是我想通过模板参数包传递范围。我知道例如 Range<float>(0,1);
是一个非类型模板参数,所以一种解决方法是像这样重构 struct Range
template<typename T,T _MIN, T _MAX>
struct Range{
static constexpr T MIN = _MIN;
static constexpr T MAX = _MAX;
};
所以我可以将 Range<T,T min, T max>
作为模板参数包传递,但是我必须将包保存在 std::tuple
中(我也不想要这个)。我的问题是,您是否看到通过重构 Range
结构或其他方式获得定义颜色 space 的任何其他可能性。 using DefineColorSpace = ColorSpace<unsigned char, ranges....>
。我知道 C++ 20
对非类型模板参数进行了巨大的重构,但我正在使用 clang
并且它们似乎 do not support 具有该功能。
任何建议都会有所帮助,谢谢)
支持文字 类,因为非类型模板参数已经在 clang trunk 中。看看吧live on godbolt:
template<typename T>
struct Range
{
T min, max;
};
template<typename T, Range<T> R>
struct SomeColorSpace
{
static constexpr Range<T> r = R;
T component1, component2;
};
using Rgb = SomeColorSpace<float, Range<float>{0.0f, 1.0f}>;
auto test()
{
Rgb color{0.4f, 0.1f};
float c1 = color.component1;
float min = Rgb::r.min;
return Rgb::r.max;
}
所以它会很快到达。在那之前,一个可能的解决方法是使用特征。看看吧live on godbolt:
template<class T, class Trait>
struct SomeColorSpace
{
static constexpr T min = Trait::min;
static constexpr T max = Trait::max;
T component1, component2;
};
struct RgbTrait
{
static constexpr float min = 0.0f;
static constexpr float max = 1.0f;
};
using Rgb = SomeColorSpace<float, RgbTrait>;
auto test()
{
Rgb color{0.4f, 0.1f};
float c1 = color.component1;
float min = Rgb::min;
return Rgb::max;
}
不太清楚你想要什么,至于颜色,r/g/b/(a) 会根据类型有相同的范围。
所以一个简单的特征允许映射 float
的 minimum/maximum 到 [0.f,1.f]
和 std::uint8_t
到 [0,255]
:
template <typename T> struct RangeTraits;
template <> struct RangeTraits<double>
{
constexpr double min = 0.;
constexpr double max = 1.;
};
template <> struct RangeTraits<std::uint8_t>
{
constexpr std::uint8_t min = 0;
constexpr std::uint8_t max = 255;
};
// ...
和
template <typename T>
struct SomeColorSpace{
std::array<T, N> components;// N is compile-time constant
// use RangeTraits<T>::min, RangeTraits<T>::max when needed.
};
另一种解释是您的模板参数“只是”初始化的默认值:
template <typename T, T DefaultMin, T DefaultMax>
struct Range{
T min = DefaultMin;
T max = DefaultMax;
// Some constructors initializing min and max...
};
但这些默认值以后应该忘记了
因此您可以执行以下操作:
std::array<Range<std::int8_t>, 2> components{Range<std::int8_t, 0, 127>, Range<std::int8_t, -10, 10>};
那么你可能会这样做:
template <typename T, T...> struct Range;
template <typename T>
struct Range<T>
{
T min;
T max;
Range(T min, T max) : min(min), max(max) {}
template <T Min, T Max,>
Range(Range<T, Min, Max>& rhs) : min(rhs.min), max(rhs.max) {}
Range(Range& rhs) = default;
// ...
};
template <typename T, T Min, T Max>
struct Range<T, Min, Max>
{
T min = Min;
T max = Max;
Range() = default;
Range(Range& rhs) = default;
// Possibly keep constructors of conversion and the one with runtime min/max
// ...
};
我正在考虑在我的程序中加入 color spaces 结构。现在你可以看到每种颜色 space 对其每个组件都有其限制。所以考虑这样的结构。
template<typename T>
struct SomeColorSpace{
T component1,component2,.....; // or std::array<T,N> components, N is compile-time const
};
现在我需要以某种方式定义一个范围,所以我创建了一个结构。
template<typename T>
struct Range{
T min, max;
// Some constructors initializing min and max...
};
现在我需要我的颜色 space 结构来了解其每个组件的范围。但如您所见,我不能只在我的结构中保留 std::array<Ranges<T>,N> ranges
,因为范围因类型而异。例如考虑 struct RGB
每个分量可能是 float
或 unsigned char
所以当分量是 float
时每个分量的范围变成 [0,1];
并且当它是无符号字符,它是 [0,255];
。为每种情况编写模板专业化是一种解决方案,但我想要这样的签名。 using RGBFloat = RGB<float,Range<float>...>
。我的意思是我想通过模板参数包传递范围。我知道例如 Range<float>(0,1);
是一个非类型模板参数,所以一种解决方法是像这样重构 struct Range
template<typename T,T _MIN, T _MAX>
struct Range{
static constexpr T MIN = _MIN;
static constexpr T MAX = _MAX;
};
所以我可以将 Range<T,T min, T max>
作为模板参数包传递,但是我必须将包保存在 std::tuple
中(我也不想要这个)。我的问题是,您是否看到通过重构 Range
结构或其他方式获得定义颜色 space 的任何其他可能性。 using DefineColorSpace = ColorSpace<unsigned char, ranges....>
。我知道 C++ 20
对非类型模板参数进行了巨大的重构,但我正在使用 clang
并且它们似乎 do not support 具有该功能。
任何建议都会有所帮助,谢谢)
支持文字 类,因为非类型模板参数已经在 clang trunk 中。看看吧live on godbolt:
template<typename T>
struct Range
{
T min, max;
};
template<typename T, Range<T> R>
struct SomeColorSpace
{
static constexpr Range<T> r = R;
T component1, component2;
};
using Rgb = SomeColorSpace<float, Range<float>{0.0f, 1.0f}>;
auto test()
{
Rgb color{0.4f, 0.1f};
float c1 = color.component1;
float min = Rgb::r.min;
return Rgb::r.max;
}
所以它会很快到达。在那之前,一个可能的解决方法是使用特征。看看吧live on godbolt:
template<class T, class Trait>
struct SomeColorSpace
{
static constexpr T min = Trait::min;
static constexpr T max = Trait::max;
T component1, component2;
};
struct RgbTrait
{
static constexpr float min = 0.0f;
static constexpr float max = 1.0f;
};
using Rgb = SomeColorSpace<float, RgbTrait>;
auto test()
{
Rgb color{0.4f, 0.1f};
float c1 = color.component1;
float min = Rgb::min;
return Rgb::max;
}
不太清楚你想要什么,至于颜色,r/g/b/(a) 会根据类型有相同的范围。
所以一个简单的特征允许映射 float
的 minimum/maximum 到 [0.f,1.f]
和 std::uint8_t
到 [0,255]
:
template <typename T> struct RangeTraits;
template <> struct RangeTraits<double>
{
constexpr double min = 0.;
constexpr double max = 1.;
};
template <> struct RangeTraits<std::uint8_t>
{
constexpr std::uint8_t min = 0;
constexpr std::uint8_t max = 255;
};
// ...
和
template <typename T>
struct SomeColorSpace{
std::array<T, N> components;// N is compile-time constant
// use RangeTraits<T>::min, RangeTraits<T>::max when needed.
};
另一种解释是您的模板参数“只是”初始化的默认值:
template <typename T, T DefaultMin, T DefaultMax>
struct Range{
T min = DefaultMin;
T max = DefaultMax;
// Some constructors initializing min and max...
};
但这些默认值以后应该忘记了
因此您可以执行以下操作:
std::array<Range<std::int8_t>, 2> components{Range<std::int8_t, 0, 127>, Range<std::int8_t, -10, 10>};
那么你可能会这样做:
template <typename T, T...> struct Range;
template <typename T>
struct Range<T>
{
T min;
T max;
Range(T min, T max) : min(min), max(max) {}
template <T Min, T Max,>
Range(Range<T, Min, Max>& rhs) : min(rhs.min), max(rhs.max) {}
Range(Range& rhs) = default;
// ...
};
template <typename T, T Min, T Max>
struct Range<T, Min, Max>
{
T min = Min;
T max = Max;
Range() = default;
Range(Range& rhs) = default;
// Possibly keep constructors of conversion and the one with runtime min/max
// ...
};