如何规避英特尔C++编译器的"decltype"和继承问题?

How to circumvent Intel C++ compiler's issue with `decltype` and inheritance?

本文关键字:decltype 问题 继承 何规避 英特尔 C++ 编译器      更新时间:2023-10-16

今天我非常惊讶地发现英特尔的icpc(版本14.0.2,使用std=c++0x)无法编译以下代码片段。


#include <type_traits>
namespace traits_tests {
  template<typename>
  struct sfinae_true : std::true_type {};
  template<typename T>
  static auto value_type(int) -> sfinae_true<typename T::value_type>;
  template<typename T>
  static auto value_type(void*) -> std::false_type;
}
template<typename C>
struct has_value_type
  : decltype(traits_tests::value_type<C>(0)) {};

抱怨最后一行:

inc/traits.h(258): error: expected an identifier
    : decltype(traits_tests::value_type<C>(0)) {};
      ^

代码在clanggcc下工作良好。

我真的不喜欢完全重写以使它在有缺陷的编译器中工作(为什么商业编译器总是有缺陷?)

  • 是否有一种更简单的方法,而不是完全不同的SFINAE模式,使其与icc一起工作?

EDIT:是的,我知道icc从一段时间以来支持decltype。但是在上面的特定上下文中,icc不能支持它。还要注意,使用std=c++11而不是std=c++0x没有区别。

正如问题和评论中所述,decltypeicc中得到支持已经有一段时间了;问题是,由于编译器中的一个严重错误,它不是在所有上下文中都可用。


更具体地说,它不能在指定类的基类时直接使用,这需要我们编写一个变通方法。

如果我们不能直接使用,就让我们间接使用(通过别名模板)!

示例解决方案

template<class T>
using identity_hack = T;
template<typename C>
struct has_value_type
  : identity_hack<decltype (traits_tests::value_type<C> (0))>
{ }

注意:上面有很多变化,例如,如果不想声明自己的东西,可以使用std::enable_if<true, decltype (...)>::type作为替代

您可以使用基于模板的解决方案-任何标准类型,接受模板类型参数并将其暴露为typedef,然后将其包装在仅为ICC定义的宏中,例如

#ifdef __INTEL_COMPILER
#include <utility>
#define decltype(...) 
  std::pair<decltype(__VA_ARGS__), int>::first_type
#endif

允许您的示例编译而无需更改。

一旦你使用的所有版本的ICC的错误被修复,你可以删除宏定义而不改变任何其他代码。

(参见对类似MSVC问题的回答)