【问题标题】:Why is the code accepted by clang but rejected by vc++?为什么代码被clang接受却被vc++拒绝了?
【发布时间】:2014-09-02 20:02:52
【问题描述】:

clang 3.4 接受以下代码;而 vc++ NOV 2013 CTP 拒绝它并出现错误:

error C2668: 'AreEqual' : ambiguous call to overloaded function
template<class headT, class... tailTypes>
constexpr headT&& __GetFirst__(headT&& value, tailTypes&&...)
{
    return static_cast<headT&&>(value);
};

template<class T>
constexpr bool AreEqual(const T& a, const T& b)
{   
    return a == b;
}

template<class headT, class... tailTypes>
constexpr bool AreEqual(const headT& head_value, const tailTypes&... tail_values)
{
    return AreEqual(head_value, __GetFirst__(tail_values...))
           && AreEqual(tail_values...);
}

int main()
{
    AreEqual(1, 1, 2, 1);  
}

根据 C++14 标准,哪个编译器是正确的?

更新:完整的错误信息:

error C2668: 'AreEqual' : ambiguous call to overloaded function
1>          d:\projects\ktl\test\main.cpp(20): could be 'bool AreEqual<headT,int>(const headT &,const int &)'
1>          with
1>          [
1>              headT=int
1>          ]
1>          d:\projects\ktl\test\main.cpp(8): or       'bool AreEqual<headT>(const T &,const T &)'
1>          with
1>          [
1>              headT=int
1>  ,            T=int
1>          ]
1>          while trying to match the argument list '(const int, const int)'
1>
1>Build FAILED.

【问题讨论】:

  • 旁注:__GetFirst__ 是保留名称。
  • 你能发布完整的错误信息吗?
  • 不知道哪个是正确的,但简单的解决方法是让可变参数采用 3+ 参数
  • +1 谢谢。为您从错误消息中删除了语法着色。

标签: c++ visual-c++ c++11 compiler-errors clang


【解决方案1】:

Clang(和 GCC)的行为是正确的。您可以阅读标准的 §14.8.2.4 [temp.deduct.partial],了解如何完成函数模板的部分排序,但该子条款 p8 中给出的示例直接涵盖了这种情况:

template<class... Args> void f(Args... args); // #1
template<class T1, class... Args> void f(T1 a1, Args... args); // #2
template<class T1, class T2> void f(T1 a1, T2 a2); // #3
f(); // calls #1
f(1, 2, 3); // calls #2
f(1, 2); // calls #3; non-variadic template #3 is more
         // specialized than the variadic templates #1 and #2

【讨论】:

  • +1。还为该子条款添加了[bracked subsection] 标识符,以便在不同版本的标准中更容易找到。 (特定的子句#s 移动,但那些标识符是固定的)
  • @BillyONeal 我会为那些标识符被修复(basic.lookup.koenig->basic.lookup.argdep :))而争吵,但点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-12-08
  • 2010-09-08
  • 1970-01-01
  • 1970-01-01
  • 2014-09-02
  • 2019-01-31
  • 1970-01-01
相关资源
最近更新 更多