Constexpr 作为模板函数中的数组大小(GCC 与 Intel)

Constexpr as Array Size in Template Function (GCC vs Intel)

我正在研究用 C++11 编写的科学代码。此代码的关键操作是在 3D 数组上执行的。这样的数组也经常传递给其他函数。在实现一些新功能时,我使用模板和 运行 来解决以下问题:代码使用 gcc 5.4(也测试了 7.2)编译良好,但使用英特尔 C++ 编译器 ICC 16.0(也测试了 18.0)它不编译,所以我想知道我的代码是否不符合标准,或者其中一个编译器是否行为不端。

一个最小的示例代码如下所示(实际上它是 3D 数组):

class Constants {   
   static constexpr int value_ = 2;

public:    
   static constexpr inline int V() { return value_; }    
};

typedef Constants CC;

template<int N>
class Terror {    
public:
  template<class T>
  void F(T (&a)[CC::V()]) {}
};

int main() {
  int array[CC::V()];    
  Terror<42> ter = Terror<42>();    
  ter.F(array);
}

我知道传递一个 (3D) 普通 C 数组,其大小通过 constexpr 确定,这不是经典方法,但如果需要,我可以详细说明其原因。

我尝试通读 C++11 标准,但没有找到对我的问题的清晰描述(至少对我而言)。

ICC 抛出的错误是这样的:

main.cpp(15): error: no instance of function template "Terror<N>::F [with N=42]" matches the argument list
            argument types are: (int [2])
            object type is: Terror<42>
   ter.F(array); 
       ^
template_class.h(10): note: this candidate was rejected because at least one template argument could not be deduced
    void F(T (&a)[CC::V()]) {}
         ^

compilation aborted for main.cpp (code 2)

有趣的是,它适用于 (3D-)std::array 或者如果两个模板之一 N/T 不存在。

这是一个 ICC 错误。

谢天谢地,有一个非常简单的解决方法,就是将该值存储在 Terror:

template<int N>
class Terror {    
    static constexpr size_t M = CC::V();
public:
    template<class T>
    void F(T (&a)[M]) {}
};

ICC 16 和 17 都接受您的程序进行此更改。