Function Template Specialization on Function Pointers

China☆狼群 提交于 2019-12-24 02:56:22

问题


I have a sanitization function that I want to run on (traditional) pointer types only.

My problem is with function templates I can get as far as limiting the function to only pointers, however because of casting rule differences between function pointers and regular pointers, I run into problems.

The Sanitize() function needs to run against a whole slew of types, some of which are pointers and need to be sanitized, others of which are function pointers of varying arity and parameter types and should not be sanitized, and some of which are non-pointer data types which also should not be sanitized.

Anything obvious I'm missing?

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

回答1:


While this problem could be solved manually, its easiest to utilize Boosts type traits and SFINAE helper to selectively disable the overload for pointers if T* is a function pointer:

template<typename T>
typename boost::disable_if<boost::is_function<T>, T*>::type
Sanitize(T* value)
{
    // ...
}



回答2:


How about this? Tested online using 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;
}



回答3:


Am I missing something? The following code compiles fine ( on 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;
  }



回答4:


As an explanation: you are trying to create a partial specialization of a function template. C++ just doesn’t allow that, full stop. Partial specializations only exist for class templates.

gf has posted the solution: use SFINAE (preferably via Boost).




回答5:


I met similar problem in g++. I solved on a standard way, but I knew the possible function signatures. What I did, I created some template specialization for the possible function pointers.

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

Output:

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'

I hope I could help...



来源:https://stackoverflow.com/questions/1794640/function-template-specialization-on-function-pointers

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!