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

发布于 2024-11-02 21:47:41 字数 761 浏览 0 评论 0原文

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

此代码为字符串类生成一个编译错误,指出这两个重载都无法转换所有参数类型。然而,对于向量来说它编译得很好。当参数不是 InsertSig 类型时,重载解析不应该选择 CheckInsert(...) 吗?

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 compile 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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

初吻给了烟 2024-11-09 21:47:42

std::string::insert 不采用 const char& 参数,而仅采用 char

此外,根据实现在 C++11 支持方面的进展,所有容器都可能使用 const_iterator(而不是迭代器)来指示位置。

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.

青巷忧颜 2024-11-09 21:47:41

请尝试这样做:

#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)无法用于获取要插入的可转换为给定签名的成员函数指针,它将无法替换虚拟参数,因此将恢复为省略号版本。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文