简体   繁体   English

ADL与表达SFINAE相关的GCC 4.7.2问题

[英]ADL related GCC 4.7.2 issue with expression SFINAE

Take the following code, which is characterized by 采用以下代码,其特点是

  1. Reliance on ADL for a specific behavior ( volume ) 依赖于ADL的特定行为( volume
  2. Using decltype for return type and relying on SFINAE to discard extra overloads 使用decltype作为返回类型并依赖SFINAE来丢弃额外的重载
namespace Nature {
   struct Plant {};
   double volume(Plant){ return 3.14; }
}

namespace Industrial {
   struct Plant {};
   double volume(Plant) { return 100; }
}


namespace SoundEffects {
   // A workaround for GCC, but why?
   ////template<class T> void volume();

   template<class aSound>
   auto mix(aSound& s) -> decltype(volume(s)*0.1)
   {
      return volume(s)*.1;
   }

   struct Samples {
      Nature::Plant  np;
      Industrial::Plant ip;
   };


   inline double mix(const Samples& s) {
      return mix(s.np) + mix(s.ip);
   }
}

int main()
{
   SoundEffects::Samples s;
   assert( mix(s) ==  100*.1 + 3.14*.1 );
}

The code as presented (without the template<class T> void volume() line), VS 2012 and clang 3.5 compiles successfully, and runtime is as expected. 显示的代码(没有template<class T> void volume()行),VS 2012和clang 3.5成功编译,运行时是预期的。 However, GCC 4.7.2 says: 但是,GCC 4.7.2说:

template-function-overload.cpp: In substitution of 'template<class aSound> decltype ((volume(s) * 1.0000000000000001e-1)) SoundEffects::mix(aSound&) [with aSound = SoundEffects::Samples]':
template-function-overload.cpp:46:4:   required from here
template-function-overload.cpp:23:9: error: 'volume' was not declared in this scope
template-function-overload.cpp:23:9: note: suggested alternatives:
template-function-overload.cpp:9:11: note:   'Nature::volume'
template-function-overload.cpp:14:11: note:   'Industrial::volume'

With the extra template volume line, all three compile and run fine. 使用额外的template volume行,所有三个编译并运行正常。

So, there is clearly a compiler defect here. 所以,这里显然存在编译器缺陷。 My question is, which compiler is the defective one? 我的问题是,哪个编译器是有缺陷的? And which C++ standard is being violated? 哪个C ++标准被违反了?

This was a bug which was fixed since GCC 4.8 . 这是自GCC 4.8以来修复的错误。 Here's a simplified version of the code that gives the same error: 这是代码的简化版本 ,它提供了相同的错误:

template<class T>
auto buzz(T x) -> decltype(foo(x));

void buzz(int);

int main() {
    buzz(5); // error: 'foo' was not declared in this scope
}

In mix(s) , both overloads of SoundEffects::mix are compiled into the set of candidate overloads via ADL ( SoundEffects is an associated namespace of SoundEffects::Sample ). mix(s)SoundEffects::mix两个重载都通过ADL编译成候选重载集( SoundEffectsSoundEffects::Sample的关联命名空间)。 The function template overload is evaluated for viability. 评估函数模板重载的可行性。 The error occurs because volume(s) cannot be resolved to a suitable overload either via pure unqualified lookup or ADL for Sample . 错误发生,因为volume(s)不能被解析为一个合适的过载或者通过纯不合格查找或ADL为Sample

The reason this should pass is that when lookup fails a substitution failure should occur (since volume(s) is dependent) and the template should be rejected from overload resolution. 应该通过的原因是当查找失败时,应该发生替换失败(因为volume(s)是依赖的),并且应该从重载解析中拒绝模板。 This would leave mix(const Sample&) as the only viable overload to select. 这将使mix(const Sample&)成为唯一可行的重载选择。 The fact that there is a hard error is clearly a sign that this GCC version has a faulty SFINAE implementation. 存在硬错误的事实显然表明该GCC版本具有错误的SFINAE实现。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM