【问题标题】:Determine if a type has particular member function signature确定类型是否具有特定的成员函数签名
【发布时间】:2011-04-21 18:15:06
【问题描述】:
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(...) 吗?

【问题讨论】:

  • 你得到什么编译错误?
  • @Tim error C2665: 'CheckSignature::CheckInsert' : 2 个重载都不能转换所有参数类型
  • 你的InsertSig是什么?
  • 下面是指向成员函数的指针:typedef typename U::iterator (U::*InsertSig)(typename U::iterator, typename const U::value_type &amp;);

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


【解决方案1】:

试试这个:

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

【讨论】:

  • 为我编译的,但 ::value 总是错误的。
  • 啊,在 VisualStudio 中,vector::insert 签名采用const_iterator——而不是iterator。一旦我更改了InsertSig typedef,它就对我有用。
  • 啊,我没有意识到这种歧义在于 insert() 函数的各种重载,而不是 CheckInsert()。谢谢!
  • 我注意到地图和设置失败了。这似乎与这些成员函数是继承的事实有关。有没有办法解决这个问题?
  • 是的,这是一个经典问题。在 boost 邮件列表上有一个讨论:boost.2283326.n4.nabble.com/…
【解决方案2】:

std::string::insert 不采用 const char&amp; 参数,而只是采用 char

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-01-08
    • 2015-08-03
    • 2021-12-29
    • 1970-01-01
    • 2022-12-12
    • 1970-01-01
    • 2016-06-20
    • 1970-01-01
    相关资源
    最近更新 更多