如何获取 std::complex<T> 的基础类型并在 class 中使用它
How to get the type underlying std::complex<T> and use it in a class
我正在编写一个数据处理器,希望能够执行实到实、实到复杂的计算。我现在的设置:
// class to hold various data types
template <typename T>
class DataArray
{
public:
DataArray(){};
T *ptr;
};
// Processing configuration
template <typename T>
class Config
{
public:
Config(){};
T var;
};
// The data processor itself, takes input, output array and the processing configuration
template <typename Tin, typename Tout>
class Process
{
public:
DataArray<Tin> *in;
DataArray<Tout> *out;
Config<Tout> *config;
Process(){};
Process(DataArray<Tin> *in_, DataArray<Tout> *out_, Config<Tout> *config_)
{
in = in_;
out = out_;
config = config_;
}
};
目前我可以进行实对实的处理如下:
int main()
{
DataArray<int16_t> input;
DataArray<float> output;
Config<float> config;
// real 2 real processing
Process<int16_t, float> P1(&input, &output, &config); // works fine
return 0;
}
我面临的问题是,当我想做实数到复数的处理时,我仍然需要我的Config
在std::complex<T>
的底层类型中。我如何更改 Process
class(或任何其他 class),以便我可以创建一个 class Process<int16_t, std::complex<float>>
,它知道它需要一个 Config<float>
?
int main()
{
DataArray<int16_t> input;
DataArray<std::complex<float>> output_complex;
Config<float> config;
// real 2 complex processing
Process<int16_t, std::complex<float>> P2(&input, &output, &config); // Obviously does not work
return 0;
}
跟进问题
感谢 Remy 的回答,我现在可以在 class Process
中获取 std::complex 的类型。如果我有一个带有模板函数的命名空间,我将如何获得该 function/namespace 中的基础类型?以下工作,但感觉有点笨拙。这意味着我必须在每个内核中重复 using T = typename helper::value_type_of<Tout>::type;
行,对吗?
// namespace with computation kernels
namespace kernels
{
// define ConfigType in the kernel namespace?
template <typename T>
using ConfigType = Config<typename helper::value_type_of<T>::type>;
template <typename Tin, typename Tout, bool IQ>
void bfpw(ConfigType<Tout> *BFC, Tin *RF, Tout *BF)
{
// get type of Tout: std::complex<float> or float
using T = typename helper::value_type_of<Tout>::type;
T variable = BFC->var;
}
}
template <typename Tin, typename Tout>
Process<Tin, Tout>::Process(DataArray<Tin> *in_, DataArray<Tout> *out_, ConfigType *config_)
{
in = in_;
out = out_;
config = config_;
kernels::bfpw<Tin, Tout, true>(config, in->ptr, out->ptr); // call the kernel
}
一种方法是定义一个辅助模板,Process
可以使用它来检测 Tout
是否是 std::complex
,如果是,那么它可以使用 Tout
的value_type
成员,否则可以用Tout
as-is.
例如:
namespace helper {
template<typename T>
struct value_type_of {
using type = T;
};
template<typename T>
struct value_type_of<std::complex<T>> {
using type = typename std::complex<T>::value_type;
// or simply: using type = T;
};
}
template <typename Tin, typename Tout>
class Process
{
public:
using ConfigType = Config<typename helper::value_type_of<Tout>::type>;
...
ConfigType *config;
Process(){};
Process(..., ConfigType *config_)
{
...
config = config_;
}
};
这样,Process<..., float>
和 Process<..., std::complex<float>>
都会接受 Config<float>
。
我正在编写一个数据处理器,希望能够执行实到实、实到复杂的计算。我现在的设置:
// class to hold various data types
template <typename T>
class DataArray
{
public:
DataArray(){};
T *ptr;
};
// Processing configuration
template <typename T>
class Config
{
public:
Config(){};
T var;
};
// The data processor itself, takes input, output array and the processing configuration
template <typename Tin, typename Tout>
class Process
{
public:
DataArray<Tin> *in;
DataArray<Tout> *out;
Config<Tout> *config;
Process(){};
Process(DataArray<Tin> *in_, DataArray<Tout> *out_, Config<Tout> *config_)
{
in = in_;
out = out_;
config = config_;
}
};
目前我可以进行实对实的处理如下:
int main()
{
DataArray<int16_t> input;
DataArray<float> output;
Config<float> config;
// real 2 real processing
Process<int16_t, float> P1(&input, &output, &config); // works fine
return 0;
}
我面临的问题是,当我想做实数到复数的处理时,我仍然需要我的Config
在std::complex<T>
的底层类型中。我如何更改 Process
class(或任何其他 class),以便我可以创建一个 class Process<int16_t, std::complex<float>>
,它知道它需要一个 Config<float>
?
int main()
{
DataArray<int16_t> input;
DataArray<std::complex<float>> output_complex;
Config<float> config;
// real 2 complex processing
Process<int16_t, std::complex<float>> P2(&input, &output, &config); // Obviously does not work
return 0;
}
跟进问题
感谢 Remy 的回答,我现在可以在 class Process
中获取 std::complex 的类型。如果我有一个带有模板函数的命名空间,我将如何获得该 function/namespace 中的基础类型?以下工作,但感觉有点笨拙。这意味着我必须在每个内核中重复 using T = typename helper::value_type_of<Tout>::type;
行,对吗?
// namespace with computation kernels
namespace kernels
{
// define ConfigType in the kernel namespace?
template <typename T>
using ConfigType = Config<typename helper::value_type_of<T>::type>;
template <typename Tin, typename Tout, bool IQ>
void bfpw(ConfigType<Tout> *BFC, Tin *RF, Tout *BF)
{
// get type of Tout: std::complex<float> or float
using T = typename helper::value_type_of<Tout>::type;
T variable = BFC->var;
}
}
template <typename Tin, typename Tout>
Process<Tin, Tout>::Process(DataArray<Tin> *in_, DataArray<Tout> *out_, ConfigType *config_)
{
in = in_;
out = out_;
config = config_;
kernels::bfpw<Tin, Tout, true>(config, in->ptr, out->ptr); // call the kernel
}
一种方法是定义一个辅助模板,Process
可以使用它来检测 Tout
是否是 std::complex
,如果是,那么它可以使用 Tout
的value_type
成员,否则可以用Tout
as-is.
例如:
namespace helper {
template<typename T>
struct value_type_of {
using type = T;
};
template<typename T>
struct value_type_of<std::complex<T>> {
using type = typename std::complex<T>::value_type;
// or simply: using type = T;
};
}
template <typename Tin, typename Tout>
class Process
{
public:
using ConfigType = Config<typename helper::value_type_of<Tout>::type>;
...
ConfigType *config;
Process(){};
Process(..., ConfigType *config_)
{
...
config = config_;
}
};
这样,Process<..., float>
和 Process<..., std::complex<float>>
都会接受 Config<float>
。