C++ C+中的编译时数组选择+;

C++ C+中的编译时数组选择+;,c++,templates,c++17,constexpr,template-specialization,C++,Templates,C++17,Constexpr,Template Specialization,我有一个类,它保存一个基于编译时参数的数组(用于过滤器)。例如: template<class Real, unsigned N> class foo { public: // stuff ... private: static const constexpr std::array<Real, unsigned N> m_h; }; 如果N=4和Real=float,我想 m_h = {0.4829629f, 0.8365163f, 0.2241438f, -

我有一个类,它保存一个基于编译时参数的数组(用于过滤器)。例如:

template<class Real, unsigned N>
class foo {
public:
  // stuff ...
private:
   static const constexpr std::array<Real, unsigned N> m_h;
};
如果
N=4
Real
=
float
,我想

m_h = {0.4829629f, 0.8365163f, 0.2241438f, -0.1294095f};
如果
N=6
,并且
Real=double
,我希望数字完全不同:

m_h = {0.332670552950082615998, 0.806891509311092576494, 0.45987750211849157009, -0.1350110200102545886963899, -0.0854412738820266616928191, 0.0352262918857095366027};

实现这一目标最优雅的语法是什么?我所发现的最接近的是Boost,它通过首先按位数对
Real
类型进行分类,并可转换为float、double和long double来实现这一目标。然后介绍一个
foo\u detail
类,该类提供函数
get\u constants()
,并选择运行时所需的常量。Boost当然支持许多编译器及其不同的C++11功能,因此我觉得使用(比如)C++17可能会有一个更具表现力的解决方案。

我不知道您到底想要什么,但。。。我想您可以初始化
m_h
调用
constexpr
模板函数,并对其进行完全专门化

我是说。。。您可以编写
foo()
,如下所示

template <typename Real, std::size_t N>
class foo
 {
   private:
      static constexpr std::array<Real, N> m_h { bar<Real, N>() };
 };

template <typename Real, std::size_t N>
constexpr std::array<Real, N> foo<Real, N>::m_h;
以下是完整的编译示例(使用简化的
foo


“我不知道你到底想要什么,但是……”这正是我想要的。谢谢
template <typename Real, std::size_t N>
class foo
 {
   private:
      static constexpr std::array<Real, N> m_h { bar<Real, N>() };
 };

template <typename Real, std::size_t N>
constexpr std::array<Real, N> foo<Real, N>::m_h;
template <typename Real, std::size_t N>
constexpr std::array<Real, N> bar ();

template <>
constexpr std::array<double, 4u> bar<double, 4u> ()
 { return { {0.4829629131445341,  0.8365163037378079,
             0.2241438680420133, -0.129409522551260} }; }

template <>
constexpr std::array<float, 4u> bar<float, 4u> ()
 { return { {0.4829629f, 0.8365163f, 0.2241438f, -0.1294095f} }; }

template <>
constexpr std::array<double, 6u> bar<double, 6u> ()
 { return { { 0.332670552950082615998,      0.806891509311092576494,
              0.45987750211849157009,      -0.1350110200102545886963899,
             -0.0854412738820266616928191,  0.0352262918857095366027} }; }

// as many `bar()` specializations as you want
#include <array>
#include <iostream>

template <typename Real, std::size_t N>
constexpr std::array<Real, N> bar ();

template <>
constexpr std::array<double, 4u> bar<double, 4u> ()
 { return { {0.4829629131445341,  0.8365163037378079,
             0.2241438680420133, -0.129409522551260} }; }

template <>
constexpr std::array<float, 4u> bar<float, 4u> ()
 { return { {0.4829629f, 0.8365163f, 0.2241438f, -0.1294095f} }; }

template <>
constexpr std::array<double, 6u> bar<double, 6u> ()
 { return { { 0.332670552950082615998,      0.806891509311092576494,
              0.45987750211849157009,      -0.1350110200102545886963899,
             -0.0854412738820266616928191,  0.0352262918857095366027} }; }

template <typename Real, std::size_t N>
struct foo
 {
   static constexpr std::array<Real, N> m_h { bar<Real, N>() };
 };

template <typename Real, std::size_t N>
constexpr std::array<Real, N> foo<Real, N>::m_h;

int main ()
 {
   for ( auto f : foo<double, 4u>::m_h )
      std::cout << f << ' ';

   std::cout << std::endl;

   for ( auto f : foo<float, 4u>::m_h )
      std::cout << f << ' ';

   std::cout << std::endl;

   for ( auto f : foo<double, 6u>::m_h )
      std::cout << f << ' ';

   std::cout << std::endl;
 }
template <typename Real, std::size_t N>
constexpr std::array<Real, N> bar ()
 {
   if constexpr ( std::is_same<long double, Real>::value )
    {
      if constexpr ( 4u == N )
         return { /* something */ };
      else if constexpr ( 6u == N )
         return { /* something */ };
      // else if constexpr ( ?? == N ) ...
    }
   else if constexpr ( std::is_same<double, Real>::value )
    { 
      if constexpr ( 4u == N )
         return { {0.4829629131445341,  0.8365163037378079,
                   0.2241438680420133, -0.129409522551260} }; 
      else if constexpr ( 6u == N )
         return { { 0.332670552950082615998,      0.806891509311092576494,
                    0.45987750211849157009,      -0.1350110200102545886963899,
                   -0.0854412738820266616928191,  0.0352262918857095366027} }; 
      // else if constexpr ( ?? == N ) ...
    }
   else if constexpr ( std::is_same<float, Real>::value )
    { 
      if constexpr ( 4u == N )
         return { {0.4829629f, 0.8365163f, 0.2241438f, -0.1294095f} };
      else if constexpr ( 6u == N )
         return { /* something */ };
      // else if constexpr ( ?? == N ) ...
    }
 }