功能指针的功能模板专业化

时间:2009-11-25 04:30:55

标签: c++ templates function-pointers template-specialization

我有一个清理函数,我只想在(传统)指针类型上运行。

我的问题在于函数模板我可以将函数限制为仅指针,但是由于函数指针和常规指针之间的规则差异,我遇到了问题。

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;
  }

5 个答案:

答案 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'

我希望我能帮忙......