开发者

Determine if a type has particular member function signature

开发者 https://www.devze.com 2023-02-28 03:15 出处:网络
template<typename U> struct CheckSignature { enum {SizeTrue = 1, SizeFalse = 2}; typedef char ReturnTrue[SizeTrue];
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;
}

This code generates a co开发者_运维百科mpile error for the string class saying that none of the 2 overloads could convert all argument types. However, for vector it compiles fine. Shouldn't overload resolution choose CheckInsert(...) whenever the parameter isn't of type InsertSig?


Try this instead:

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

The reason why it doesn't work is because, in your version, taking the address of the insert function will fail at the call site, not at the substitution (which is not an error). The above will make sure that if the type U (templated to T) cannot be used to obtain a member function pointer to insert which is convertable to the given signature, it will fail to substitute for the dummy parameter, and thus, revert to the ellipsis version.


The std::string::insert doesn't take a const char& parameter, but just a char.

Also, depending on how far the implementation has has come in its C++11 support, all containers might use a const_iterator (instead of iterator) to indicate the position.

0

精彩评论

暂无评论...
验证码 换一张
取 消