确定类型是否具有特定成员函数签名

时间:2011-04-21 18:15:07

标签: c++ templates visual-c++ stl

template<typename U> struct CheckSignature {
    enum {SizeTrue = 1, SizeFalse = 2};
    typedef char ReturnTrue[SizeTrue];
    typedef char ReturnFalse[SizeFalse];
    typedef typename U::iterator (U::*InsertSig)(typename U::iterator, typename const U::value_type &);
    static ReturnTrue &CheckInsert(InsertSig);
    static ReturnFalse &CheckInsert(...);
    static const bool value = (sizeof(CheckInsert(&U::insert)) == sizeof(ReturnTrue));
};

int main() {
    CheckSignature<std::string >::value; //compile error
    CheckSignature<std::vector<int> >::value; // OK
    return 0;
}

此代码为字符串类生成编译错误,指出2个重载都不能转换所有参数类型。然而,对于矢量,它编译很好。如果参数不是InsertSig类型,那么不应该重载决策选择CheckInsert(...)

2 个答案:

答案 0 :(得分:2)

请改为尝试:

#include <string>
#include <vector>
#include <iostream>

template<typename U> struct CheckSignature {
    enum {SizeTrue = 1, SizeFalse = 2};
    typedef char ReturnTrue[SizeTrue];
    typedef char ReturnFalse[SizeFalse];
    typedef typename U::iterator (U::*InsertSig)(typename U::iterator, typename U::value_type const &);
    template <InsertSig f> struct dummy_type { };
    template <typename T>
    static ReturnTrue &CheckInsert(T*, dummy_type<&T::insert> dummy = dummy_type<&T::insert>());
    static ReturnFalse &CheckInsert(...);
    static const bool value = (sizeof(CheckInsert(((U*)0))) == sizeof(ReturnTrue));
};

int main() {
    if(CheckSignature<std::string >::value) {
      std::cout << "String class has proper insert function" << std::endl;
    }; //OK, does not print, as expected.
    if(CheckSignature<std::vector<int> >::value) {
      std::cout << "Vector class has proper insert function" << std::endl;
    }; //OK, does print, as expected.
    return 0;
}

它不起作用的原因是,在您的版本中,取得插入函数的地址将在调用站点失败,而不是替换(这不是错误)。上面将确保如果类型U(模板化为T)不能用于获取可转换为给定签名的插入的成员函数指针,它将无法替换伪参数,因此,将恢复为省略号版本。

答案 1 :(得分:0)

std::string::insert不会使用const char&参数,而只需char

此外,根据C ++ 11支持实现的程度,所有容器都可以使用const_iterator(而不是迭代器)来指示位置。