我有一个清理函数,我只想在(传统)指针类型上运行。
我的问题在于函数模板我可以将函数限制为仅指针,但是由于函数指针和常规指针之间的规则差异,我遇到了问题。
Sanitize()
函数需要针对一大堆类型运行,其中一些类型是指针,需要进行清理,其他类型是不同arity和参数类型的函数指针,不应该进行清理,并且其中一些是非指针数据类型,也不应该被消毒。
我遗失了哪些明显的东西?
template<typename T>
T* Sanitize(T* value)
{
return (T*)SanitizePointer(value); //SanitizePointer returns void*, so cast is necessary
}
template<typename T>
T Sanitize(T value)
{
return value; //Non-pointers can be passed without sanitization
}
int main()
{
int a;
int* b;
int (*c)();
Sanitize(a);
Sanitize(b);
Sanitize(c); //<- ERROR
return 0;
}
答案 0 :(得分:4)
虽然可以手动解决此问题,但如果T*
是函数指针,则最容易利用Boosts类型特征和SFINAE帮助器来选择性地禁用指针的重载:
template<typename T>
typename boost::disable_if<boost::is_function<T>, T*>::type
Sanitize(T* value)
{
// ...
}
答案 1 :(得分:2)
这个怎么样? 使用Comeau C / C ++在线测试。
void* SanitizePointer( void* p )
{ return p; }
void _Sanitize( ... )
{
}
void _Sanitize( void* p )
{
SanitizePointer( p );
}
// making this a ref so as to avoid the copy, YMMV
template<typename T>
T& Sanitize(T& value)
{
_Sanitize(value);
return value;
}
int main(int argc, char* argv[])
{
int a;
int* b;
int (*c)();
Sanitize(a);
Sanitize(b);
Sanitize(c);
return 0;
}
答案 2 :(得分:0)
我错过了什么吗?以下代码编译正常(在VS2008上)
void* SanitizePointer(void* value)
{
return (void*)0;
}
template<typename T>
T* Sanitize(T* value)
{
return (T*)SanitizePointer(value); //SanitizePointer returns void*, so cast is necessary
}
template<typename T>
T Sanitize(T value)
{
return value; //Non-pointers can be passed without sanitization
}
int main()
{
int a;
int* b;
int (*c)();
Sanitize(a);
Sanitize(b);
Sanitize(c); //<- Compiles fine
return 0;
}
答案 3 :(得分:0)
作为解释:您正在尝试创建函数模板的部分特化。 C ++只是不允许这样,完全停止。部分特殊化仅适用于类模板。
gf已发布解决方案:使用SFINAE(最好通过Boost)。
答案 4 :(得分:0)
我在g ++中遇到了类似的问题。我以标准的方式解决了,但我知道可能的功能签名。我做了什么,我为可能的函数指针创建了一些模板专门化。
#include <cxxabi.h>
#include <iostream>
using std::cout;
using std::endl;
...
#define O cout << __PRETTY_FUNCTION__ << endl;
// Return the user-readable type name
//#if defined(__GNUC__) || defined(__GNUG__)
#define _TYPENAME(x) typeid(x).name()
#define TYPENAME(x) abi::__cxa_demangle(_TYPENAME(x), 0, 0, 0)
// Show type information for variables and type names as well
#define OTYP(x) cout << "(" << #x << ") <" << TYPENAME(x) << "> '" << _TYPENAME(x) << "'" << endl;
#define OVAL(x) cout << #x << " = " << x << ", <" << TYPENAME(x) << "> '" << _TYPENAME(x) << "'" << endl;
template <class T> void typ(T o()) { O; cout << "f "; OTYP(T); }
template <class T, class U> void typ(T o(U)) { O; cout << "F "; OTYP(T); OTYP(U); }
template <class T> void typ(T o(...)) { O; cout << "e "; OTYP(T); }
const char* testcs(const std::string& s) { return s.c_str(); }
void testv(const std::string& s) { }
void testvv() {}
void testvV(void) {}
void teste(...) { }
int main() {
typ(testcs);
typ(testv);
typ(testvv);
typ(testvV);
typ(teste);
}
输出:
void typ(T (*)(U)) [with T = const char*, U = const std::string&]
F (T) <char const*> 'PKc'
(U) <std::string> 'Ss'
void typ(T (*)(U)) [with T = void, U = const std::string&]
F (T) <void> 'v'
(U) <std::string> 'Ss'
void typ(T (*)()) [with T = void]
f (T) <void> 'v'
void typ(T (*)()) [with T = void]
f (T) <void> 'v'
void typ(T (*)(...)) [with T = void]
e (T) <void> 'v'
我希望我能帮忙......