【问题标题】:Templates instantiation confusion模板实例化混乱
【发布时间】:2011-12-15 10:07:52
【问题描述】:

这是我检查类是否有成员函数begin 的代码:

template<typename T> struct has_begin
{
    struct dummy {typedef void const_iterator;};
    typedef typename std::conditional< has_iterator<T>::yes, T, dummy>::type TType;
    typedef typename TType::const_iterator Iter;
    struct fallBack{ Iter begin() const ; Iter end() const;};
    struct checker : T, fallBack {};
    template <typename B, B> struct cht;
    template<typename C> static char check(cht< Iter (fallBack::*)() const, &C::begin>*); // problem is here
    template<typename C> static char (&check(...))[2];
public:
    enum {no = (sizeof(check<checker>(0))==sizeof(char)),
     yes=!no};
};

如果我将check(cht&lt; Iter (fallBack::*)() const, &amp;C::begin&gt;*);cht 的第二个参数更改为 &amp;checker::begin ,这不会改变代码的语义,因为 cht 的第二个模板参数总是 checker 由于 enum {no = (sizeof(check&lt;checker&gt;(0))==sizeof(char))

但代码更改导致 error 现在是:

prog.cpp: In instantiation of 'has_begin<std::vector<int> >':
prog.cpp:31:51:   instantiated from here
prog.cpp:23:38: error: reference to 'has_begin<std::vector<int> >::checker::begin' is ambiguous

我想知道这种行为背后的原因。

【问题讨论】:

  • 您的结构非常复杂。它应该做什么?看起来像检查类 T 是否有一个名为 begin 的成员函数
  • @VJovic 你说得对,我编辑了 Q 的第一行 :)
  • 如果进行更改会出现什么错误?
  • @AlanStokes 模糊调用错误 :(
  • @Freak 枚举:What error do you get 表示 Please post the error message you get verbatim (copy+paste)

标签: c++ templates sfinae


【解决方案1】:

来自关于 SFINAE - 替换失败不是错误的 Wikipedia 文章:

[...] 在为重载解决方案创建候选集时,部分(或全部) 该集合的候选项可能是代入推导的结果 模板参数的模板参数。如果发生错误 在替换期间,编译器从 候选集而不是因编译错误而停止 [...]

在您发布的代码中,使用参数C == typename has_begin&lt;T&gt;::checker 实例化函数模板check 时发生歧义错误,并且该替换会导致错误,因此只需从重载集中删除实例化.

如果您更改代码,&amp;checker::begin 会出现类似的歧义错误。 然而这一次,不是用模板参数 C 代替 check 函数模板的结果。 struct has_begin 的模板参数 T 的替换与 SFINAE 规则无关,因为该模板已成功实例化。

【讨论】:

  • 你的第一段对我来说没有意义。你能把原因解释清楚一点吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多