2

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

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

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

5 回答 5

4

虽然这个问题可以手动解决,但如果是函数指针,最简单的方法是利用 Boosts 类型特征和SFINAE帮助器来选择性地禁用指针的重载:T*

template<typename T>
typename boost::disable_if<boost::is_function<T>, T*>::type
Sanitize(T* value)
{
    // ...
}
于 2009-11-25T05:50:28.267 回答
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;
}
于 2009-11-25T11:00:41.657 回答
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;
  }
于 2009-11-25T05:33:27.430 回答
0

作为解释:您正在尝试创建函数模板的部分专业化。C++ 就是不允许这样做,句号。部分特化只存在于类模板中。

gf 已发布解决方案:使用 SFINAE(最好通过 Boost)。

于 2009-11-25T08:15:10.723 回答
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'

我希望我能帮助...

于 2014-03-20T16:32:50.013 回答