问题Is possible to fix the iostream cout/cerr member function pointers being printed as 1 or true?之后,我试图编写一种与C ++ 98兼容的方式来打印任何函数指针。
为此,我使用的是伪造的C ++“ variadic”模板,即,编写最多n个参数的所有函数定义。但是,我的伪可变参数仅适用于参数为0的函数指针,如以下示例所示:https://godbolt.org/z/x4TVHS
#include<iostream>
template<typename Return>
std::ostream& operator <<(std::ostream& os, Return(*pointer)() ) {
return os << (void*) pointer;
}
template<typename Return, typename T0>
std::ostream& operator <<(std::ostream& os, Return(*pointer)( const T0& t0 ) ) {
return os << (void*) pointer;
}
template<typename Return, typename T0, typename T1>
std::ostream& operator <<(std::ostream& os, Return(*pointer)( const T0& t0, const T1& t1 ) ) {
return os << (void*) pointer;
}
void fun_void_void(){};
void fun_void_double(double d){};
double fun_double_double(double d){return d;}
int main() {
std::cout << "1. " << fun_void_void << std::endl;
std::cout << "2. " << fun_void_double << std::endl;
std::cout << "3. " << fun_double_double << std::endl;
}
// Prints:
// 1. funptr 0x100401080
// 2. funptr 1
// 3. funptr 1
如果我使用C ++ 11真实可变参数模板编写等效版本,则一切正常:https://godbolt.org/z/s6wdgp
#include<iostream>
template<typename Return, typename... Args>
std::ostream& operator <<(std::ostream& os, Return(*pointer)( Args... ) ) {
return os << (void*) pointer;
}
void fun_void_void(){};
void fun_void_double(double d){};
double fun_double_double(double d){return d;}
int main() {
std::cout << "1. " << fun_void_void << std::endl;
std::cout << "2. " << fun_void_double << std::endl;
std::cout << "3. " << fun_double_double << std::endl;
}
// Prints:
// 1. funptr 0x100401080
// 2. funptr 0x100401087
// 3. funptr 0x100401093
分析代码后,我注意到这之间的唯一区别是C ++ 11示例中的类型不是const引用。然后,我从C ++ 98中删除了constness和引用,它开始起作用:https://godbolt.org/z/ZrF66b
#include<iostream>
template<typename Return>
std::ostream& operator <<(std::ostream& os, Return(*pointer)() ) {
return os << (void*) pointer;
}
template<typename Return, typename T0>
std::ostream& operator <<(std::ostream& os, Return(*pointer)( T0 ) ) {
return os << (void*) pointer;
}
template<typename Return, typename T0, typename T1>
std::ostream& operator <<(std::ostream& os, Return(*pointer)( T0, T1 ) ) {
return os << (void*) pointer;
}
void fun_void_void(){};
void fun_void_double(double d){};
double fun_double_double(double d){return d;}
int main() {
std::cout << "1. " << fun_void_void << std::endl;
std::cout << "2. " << fun_void_double << std::endl;
std::cout << "3. " << fun_double_double << std::endl;
}
// Prints:
// 1. funptr 0x100401080
// 2. funptr 0x100401087
// 3. funptr 0x100401093
为什么函数指针模板定义为const和/或引用时不匹配?
对于单个参数,您具有此模板:
template<typename Return, typename T0>
std::ostream& operator <<(std::ostream& os, Return(*pointer)( const T0& t0 ) ) {
return os << (void*) pointer;
}
它接受类型的函数
Return()(const T0& t0);
您对其进行测试的功能是
void fun_void_double(double d){};
没有T0
使模板与该函数的类型匹配。
通常,为您不拥有的类型编写包罗万象的运算符不是最佳策略。如果您想轻松地传递函数指针,则可以使用例如标签:
#include <iostream>
template <typename T>
struct as_void_impl {
T* value;
friend std::ostream& operator<<(std::ostream& out, const as_void_impl& x) {
return out << x.value;
}
};
template <typename T>
as_void_impl<T> as_void(T* t) { return {t}; }
void fun_void_double(double d){};
int main() {
std::cout << as_void(fun_void_double);
}
这具有为任何东西,但只有您明确要求的东西工作的指针的好处。