【问题标题】:templated conversion operator type deduction differs in clang and gcc模板化转换运算符类型推导在 clang 和 gcc 中有所不同
【发布时间】:2016-05-02 17:36:29
【问题描述】:

在过去的几天里,我一直在与编译器之间在模板转换运算符类型推导方面的差异作斗争,我终于将至少其中一个差异归结为堆栈溢出大小的示例:

void foo(int i);

struct any_const_reference {
  template <typename T>
  operator const T&();
};

template <typename T, typename Enable=void>
struct detect_call : std::false_type { };

template <typename T>
struct detect_call<T,
  decltype( declval<T>()( any_const_reference() ) )
> : std::true_type { };

Demo

表达式detect_call&lt;decltype(foo)&gt;::value 在clang 中给出true,在gcc 中给出false(使用我可以使用的任一编译器的任何现代版本,最新的是gcc 5.2 和clang 3.8)。问题:

  • 哪个是正确的?也就是哪个符合C++标准?
  • 造成这种差异的原因是什么?
  • 一般来说,在转换运算符(或在任何这种形式的转换运算符中,例如 template &lt;typename T&gt; operator T();)中应用于 T 的类型推导规则是什么,它们在 C++ 标准中的什么地方给出?

注意:这似乎与这个问题相似:Template argument type deduction by conversion operator(事实上,我也遇到了这个确切的差异),但我不太明白那个答案和这个案例之间的映射。如果这只是这个问题的另一个实例,那么这个问题归结为如何将该问题映射到这个用例中。

【问题讨论】:

  • 您能否在您的代码中添加一个完整的示例,并添加您正在测试的 gcc 和 clang 版本,以便其他发现此错误的人更容易找到它?
  • @xaxxon 完整的示例在演示链接中,但它基本上是那里给出的一些#includes 和调用问题中给出的表达式的main。我为后代添加了编译器版本

标签: c++ templates gcc clang++ type-deduction


【解决方案1】:

这可以简化为只是实际调用foo()

void foo(int ) { }

struct any_const_reference {
  template <typename T>
  operator const T&();
};

int main() {
    foo(any_const_reference{}); // ok on clang
                                // error on gcc
}

这是一个 gcc 错误(#63217 根据上面 TC 的评论)。根据[temp.deduct.conv],这应该将T 推导出为int,因为引用和限定符都应该被删除(在这种情况下Pconst T&amp;Aint)。

【讨论】:

  • 谢谢。 [temp.deduct.conv] 正是我一直在寻找但找不到的。
猜你喜欢
  • 2020-10-27
  • 2015-07-22
  • 2013-05-05
  • 2018-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-06
相关资源
最近更新 更多