这个问题源于需要调用遗留C例程(FFTW),它们在模板化的C ++类中具有不同的函数名称,具体取决于类型(单/双/四倍精度)。这个错误的代码示例给出了我可能想要做的一个简单示例:
#include <cstdio>
#include <cmath>
#include <typeinfo>
#include <cstdlib>
void fcnd(double *x) {
*x = pow(*x, 2);
printf("%f\n", *x);
}
void fcnf(float *x) {
*x -= 1;
printf("%f\n", *x);
}
template <typename T> class Class {
public:
void fcn() {
T *var;
if (typeid(T) == typeid(float)) {
var = (float *) malloc(sizeof(float));
} else if (typeid(T) == typeid(double)) {
var = (double *) malloc(sizeof(double));
}
*var = 1.0;
if (typeid(T) == typeid(float)) {
fcnf(var);
} else if (typeid(T) == typeid(double)) {
fcnd(var);
}
free(var);
}
};
int main() {
Class<double> x;
Class<float> y;
x.fcn();
y.fcn();
}
海湾合作委员会抱怨:
test.cpp: In instantiation of 'void Class<T>::fcn() [with T = double]': test.cpp:42:11: required from here test.cpp:22:17: error: cannot convert 'float*' to 'double*' in assignment
var = (float *) malloc(sizeof(float));
^ test.cpp:30:17: error: cannot convert 'double*' to 'float*' for argument '1' to 'void fcnf(float*)'
fcnf(var);
^ test.cpp: In instantiation of 'void Class<T>::fcn() [with T = float]': test.cpp:43:11: required from here test.cpp:24:17: error: cannot convert 'double*' to 'float*' in assignment
var = (double *) malloc(sizeof(double));
^ test.cpp:32:17: error: cannot convert 'float*' to 'double*' for argument '1' to 'void fcnd(double*)'
fcnd(var);
^
现在,我知道这里的错误是什么。我的问题是,为什么C ++不允许这样做?当然这是安全的,对吧?我认为专业化可能对此有所帮助,总是正确的方法吗?
答案 0 :(得分:5)
基于模板参数调用函数可以在C ++ 17中完成:
extension UIView {
func setNeedsLayoutForSubviews() {
self.subviews.forEach({
$0.setNeedsLayout()
$0.setNeedsLayoutForSubviews()
})
}
}
func refreshIpad() {
DispatchQueue.main.async {
self.view.setNeedsLayout()
self.view.setNeedsLayoutForSubviews()
}
}
如果您没有可用的C ++ 17,您可以使用基于template <typename T> class Class
{
public:
void fcn()
{
// one line can do it
T* var{ reinterpret_cast<T*>(std::malloc(sizeof(*var))) };
*var = 1.0;
// C++17's if constexpr does exactly what you need
if constexpr (std::is_same_v<T, float>)
{
fcnf(var);
}
else if constexpr (std::is_same_v<T, double>)
{
fcnd(var);
}
free(var);
}
};
的调度程序,其中包含模板特化或只是一个简单的重载函数。
T
注意:我希望在您的真实代码中检查调用auto set(float* f) noexcept
{
return fcnf(f);
}
auto set(double* d) noexcept
{
return fcnd(d);
}
template <typename T> class Class
{
public:
void fcn()
{
T* var{ reinterpret_cast<T*>(std::malloc(sizeof(*var))) };
*var = 1.0;
set(var); // there's a reason we have function overloading in C++
free(var);
}
};
的结果。
答案 1 :(得分:0)
为什么不定义重载函数,而不是创建模板类:
void fcn(double& x) {
fcnd(&x);
}
void fcn(float& x) {
fcnf(&x);
}
此外,如果函数的名称仅因某些标准后缀集(表示类型)而不同,您甚至可以使用宏来轻松定义所有可用函数的重载:
#include <cstdio>
#include <cmath>
#include <iostream>
using namespace std;
/*
Some C functions, actually defined elsewhere...
*/
void fcnd(double *x) {
*x = pow(*x, 2);
}
void fcnf(float *x) {
*x -= 1;
}
/*
Some macros to simplify things
*/
#define define_overloaded_function_for(name, type, suffix)\
void name(type& x) { name##suffix(&x); }
#define define_overloaded_functions_for(name)\
define_overloaded_function_for(name, float, f)\
define_overloaded_function_for(name, double, d)\
/* define_overloaded_function_for(name, long double, ld) */
/*
Define some functions
*/
define_overloaded_functions_for(fcn);
/* ...etc... */
int main(void) {
float a = 705;
double b = 2465;
cout << "~ a ~" << endl;
cout << a << endl;
fcn(a);
cout << a << endl;
cout << "~ b ~" << endl;
cout << b << endl;
fcn(b);
cout << b << endl;
}