调整检查函数参数是否存在成员函数
我一直在尝试改编this 解决方案,以启用普通(非成员)函数的存在。 在我的例子中,我有很多全局的字符串实用程序类型的函数,它们使用任何字符串类型T,例如T有一个char const* c_str() const
成员函数。调整检查函数参数是否存在成员函数
目标是消除奇怪的编译器错误消息,如果用户试图传递一些没有c_str()
成员函数的类型T,而不是编译器说的“c_str():no such member function”,I' d而是编译器说:“foo(T &):没有这样的函数”其中foo
是全局函数。
这里是适应代码:
template<bool B,typename T = void>
struct enable_if {
typedef T type;
};
template<typename T>
struct enable_if<false,T> {
};
//
// This macro is adapted from the linked-to question -- this part works fine.
//
#define DECL_HAS_MEM_FN(FN_NAME) \
template<class ClassType,typename MemFnSig> \
struct has_##FN_NAME##_type { \
typedef char yes[1]; \
typedef char no[2]; \
template<typename T,T> struct type_check; \
template<class T> static yes& has(type_check<MemFnSig,&T::FN_NAME>*); \
template<class T> static no& has(...); \
enum { value = sizeof(has<ClassType>(0)) == sizeof(yes) }; \
}
// Declare an instance of the above type that checks for "c_str()".
DECL_HAS_MEM_FN(c_str);
// Define another macro just to make life easier.
#define has_c_str(STRINGTYPE) \
has_c_str_type<STRINGTYPE,char const* (STRINGTYPE::*)() const>::value
//
// A "ValidatedStringType" is a StringType that uses the above machinery to ensure that
// StringType has a c_str() member function
//
template<class StringType>
struct ValidatedStringType {
typedef typename enable_if<has_c_str(StringType),StringType>::type type;
};
// Here's the global function where I want to accept only validated StringTypes.
template<class StringType>
void f(typename ValidatedStringType<StringType>::type const& s) {
}
struct S { // Class for testing that has c_str().
char const* c_str() const {
return 0;
}
};
struct N { // Class for testing that does not have c_str().
};
using namespace std;
int main() {
S s;
N n;
cout << has_c_str(S) << endl; // correctly prints '1'
cout << has_c_str(N) << endl; // correctly prints '0'
f(s); // error: no matching function for call to 'f(S&)'
}
然而,如上图所示,编译器不“看” f(S&)
- 为什么不呢?
如果我理解正确的问题,应用enable_if
到f
自己喜欢 下面将解决这个问题:
template<class StringType>
typename enable_if<has_c_str(StringType),StringType>::type
f(StringType const& s) {....}
希望这有助于。
但f的返回类型应该是无效的。如果省略“,StringType”,那么它是正确的并且可行。 :)但我仍然想知道为什么原稿不起作用。 – 2011-01-23 15:44:04
我无法回答你的问题(“为什么不?”),但我可以提供解决方法。但是,男人,这是丑陋的。您最终定义为每一个功能的结构和功能:
template<class StringType, class T = typename ValidatedStringType<StringType>::type>
struct f_helper {
void operator()(T const& s) {
// Put the contents of f() here
}
};
template<class StringType>
void f(StringType const &s) {
f_helper<StringType>()(s);
}
我敢肯定有,你可以写,以消除一些样板的一些预处理魔术,但它也将是相当难看:
#define DECL_VALIDATED_FUNC(RetType, name, Validator, contents) \
template<class StringType, class T = typename Validator<StringType>::type> \
struct name ## _helper { \
RetType operator()(T const& s) contents \
}; \
\
template<class StringType> \
RetType name(StringType const& s) { \
name ## _helper<StringType>()(s); \
}
DECL_VALIDATED_FUNC(void, f, ValidatedStringType, {
// put contents of f() here
}) // note the closing parenthesis
不幸的是,你不能指定默认模板参数,以免费的功能,否则你可以做:
template<class StringType, class T = typename ValidatedStringType<StringType>::type>
void f(T const& s) {}
是的,为了使错误信息更好,这太有点太丑陋了。 – 2011-01-23 04:32:59
仅供参考:f()采用S const而不仅仅是S没有区别。同样使's'const没有任何区别。最后,消除'&'没有任何区别。 – 2011-01-23 04:35:37