C++ 使用模板在编译时初始化指向数组的指针的常量向量

C++ 使用模板在编译时初始化指向数组的指针的常量向量,c++,c++11,templates,vector,metaprogramming,C++,C++11,Templates,Vector,Metaprogramming,下面的类不会在C++11下编译;当前的循环只能在运行时执行,因此循环中的模板类静态函数调用会出现“char(*)[i]是可变修改类型”错误: #include <cstddef> #include <vector> template <std::size_t N> class Foo { private: const std::vector<char(*)[]> bar = bar_init(); static std::vec

下面的类不会在C++11下编译;当前的循环只能在运行时执行,因此循环中的模板类静态函数调用会出现“char(*)[i]是可变修改类型”错误:

#include <cstddef>
#include <vector>

template <std::size_t N>
class Foo
{
private:
    const std::vector<char(*)[]> bar = bar_init();

    static std::vector<char(*)[]> bar_init()
    {
        std::vector<char(*)[]> init;

        for (size_t i = N; i > 0; i >>= 1)
        {
            auto ptr_to_array = MyClass<char(*)[i]>::static_return_ptr_to_array();
            init.emplace_back(reinterpret_cast<char(*)[]>(ptr_to_array));
        }

        return init;
    }
};
#包括
#包括
模板
福班
{
私人:
const std::vector bar=bar_init();
静态标准::向量条_init()
{
std::向量初始化;
对于(大小i=N;i>0;i>>=1)
{
自动ptr_to_array=MyClass::static_return_ptr_to_array();
初始安放(重新解释投射(ptr到阵列));
}
返回init;
}
};
有没有一种方法可以在初始化函数中使用模板实现相同的效果?也就是说,在“Foo”类实例化中将大小为log2(N)的“bar”初始化为指向char数组的指针的常量向量,每个向量元素包含例如N=32的输出:

MyClass<char(*)[32]>::static_return_ptr_to_array();
MyClass<char(*)[16]>::static_return_ptr_to_array();
MyClass<char(*)[8]>::static_return_ptr_to_array();

//etc...
MyClass::static_return_ptr_to_array();
MyClass::static_return_ptr_to_array();
MyClass::static_return_ptr_to_array();
//等等。。。

我认为这里的关键观点是,你不能写:

int i = ?? // automatic variable
auto val = MyClass<char(*)[i]>::static_return_ptr_to_array()

基本上,这个想法是您有一个静态的分配器函数数组,然后索引到其中。(使用模板初始化映射可能有一些巧妙的方法。不过我可能会手工编写,可能是使用预处理器宏)。

我认为这里的关键观点是,您不能编写:

int i = ?? // automatic variable
auto val = MyClass<char(*)[i]>::static_return_ptr_to_array()
基本上,这个想法是您有一个静态的分配器函数数组,然后索引到其中。(可能有一些聪明的方法可以使用模板来初始化映射。不过,我可能只是手工写出来——可能是使用预处理器宏)。

类似(在c++11中)

模板
结构标记{};
void init(std::vector&result,tag){}
模板
void init(std::vector&result,tag)
{
auto ptr_to_array=MyClass::static_return_ptr_to_array;
结果:安放回(重新解释投射(ptr到阵列));
init(result,tag>1)>{});
}
模板
福班
{
私人:
const std::vector bar=bar_init();
静态标准::向量条_init()
{
std::向量结果;
init(结果,标记{});
返回结果;
}
};
在c++17中,使用if constexpr和no标记可以进一步简化这一过程。此外,请注意,
std::vector
是不可移植的,因为vector需要一个完整的类型。

类似(在c++11中)

模板
结构标记{};
void init(std::vector&result,tag){}
模板
void init(std::vector&result,tag)
{
auto ptr_to_array=MyClass::static_return_ptr_to_array;
结果:安放回(重新解释投射(ptr到阵列));
init(result,tag>1)>{});
}
模板
福班
{
私人:
const std::vector bar=bar_init();
静态标准::向量条_init()
{
std::向量结果;
init(结果,标记{});
返回结果;
}
};

在c++17中,使用if constexpr和no标记可以进一步简化这一过程。此外,请注意,
std::vector
是不可移植的,因为vector需要一个完整的类型。

如果您定义索引容器类型特征(或者使用
std::index_序列
,很遗憾,只能从C++14开始使用)

(假设
MyClass
中的静态
getPtr()
方法返回
char**
char**
bar
向量)

下面是一个完整的编译示例

template <typename T>
struct MyClass;

template <std::size_t Dim>
struct MyClass<char(*)[Dim]>
 {
   static char ** getPtr ()
    { static char ach[Dim]; static char * ret { ach } ; return &ret; }
 };

template <std::size_t ...>
struct indexList
 { };

template <std::size_t, typename>
struct iLH;

template <std::size_t N, std::size_t ... Is>
struct iLH<N, indexList<Is...>> : public iLH<(N >> 1), indexList<Is..., N>>
 { };

template <std::size_t ... Is>
struct iLH<0U, indexList<Is...>>
 { using type = indexList<Is...>; };

template <std::size_t N>
struct getIndexList : public iLH<N, indexList<>>
 { };

template <std::size_t N>
using getIndexList_t = typename getIndexList<N>::type;

template <std::size_t N>
class Foo
 {
   private:
      const std::vector<char **> bar = bar_init (getIndexList_t<N>{});

      template <std::size_t ... Is>
      static std::vector<char **> bar_init (indexList<Is...> const &)
       {
         std::vector<char **> init { MyClass<char(*)[Is]>::getPtr()... };

         return init;
       }
 };

int main ()
 {
   Foo<32U>  f32;
 }
模板
结构MyClass;
模板
结构MyClass
{
静态字符**getPtr()
{static char ach[Dim];static char*ret{ach};return&ret;}
};
模板
结构索引
{ };
模板
结构iLH;
模板
结构iLH:public iLH>1),索引列表>
{ };
模板
结构iLH
{使用type=indexList;};
模板
结构getIndexList:公共iLH
{ };
模板
使用getIndexList\u t=typename getIndexList::type;
模板
福班
{
私人:
const std::vector bar=bar_init(getIndexList_t{});
模板
静态标准::向量条初始化(索引列表常量&)
{
std::vector init{MyClass::getPtr()…};
返回init;
}
};
int main()
{
富f32;
}

如果定义索引容器类型特征(或者使用
std::index_序列
,很遗憾,只能从C++14开始使用)

(假设
MyClass
中的静态
getPtr()
方法返回
char**
char**
bar
向量)

下面是一个完整的编译示例

template <typename T>
struct MyClass;

template <std::size_t Dim>
struct MyClass<char(*)[Dim]>
 {
   static char ** getPtr ()
    { static char ach[Dim]; static char * ret { ach } ; return &ret; }
 };

template <std::size_t ...>
struct indexList
 { };

template <std::size_t, typename>
struct iLH;

template <std::size_t N, std::size_t ... Is>
struct iLH<N, indexList<Is...>> : public iLH<(N >> 1), indexList<Is..., N>>
 { };

template <std::size_t ... Is>
struct iLH<0U, indexList<Is...>>
 { using type = indexList<Is...>; };

template <std::size_t N>
struct getIndexList : public iLH<N, indexList<>>
 { };

template <std::size_t N>
using getIndexList_t = typename getIndexList<N>::type;

template <std::size_t N>
class Foo
 {
   private:
      const std::vector<char **> bar = bar_init (getIndexList_t<N>{});

      template <std::size_t ... Is>
      static std::vector<char **> bar_init (indexList<Is...> const &)
       {
         std::vector<char **> init { MyClass<char(*)[Is]>::getPtr()... };

         return init;
       }
 };

int main ()
 {
   Foo<32U>  f32;
 }
模板
结构MyClass;
模板
结构MyClass
{
静态字符**getPtr()
{static char ach[Dim];static char*ret{ach};return&ret;}
};
模板
结构索引
{ };
模板
结构iLH;
模板
结构iLH:public iLH>1),索引列表>
{ };
模板
结构iLH
{使用type=indexList;};
模板
结构getIndexList:公共iLH
{ };
模板
使用getIndexList\u t=typename getIndexList::type;
模板
福班
{
私人:
const std::vector bar=bar_init(getIndexList_t{});
模板
静态标准::向量条初始化(索引列表常量&)
{
std::vector init{MyClass::getPtr()…};
返回init;
}
};
int main()
{
富f32;
}

可能重复的
索引\u序列
可能会有所帮助。您能给我们看一下您的
MyClass
?或者它的简化(但可编译)版本?@下划线这里的问题似乎部分适用,但在我的情况下,我的向量只是常量,而不是常量静态,每个“Foo”的实例化可能使用不同的N值进行模板化,因此bar的初始化过程似乎需要同时使用模板专门化和运行时调用。@max66我对示例中发布的代码进行了一些修改,以便更容易理解我遇到的问题。在actu中
template <std::size_t ...>
struct indexList
 { };
template <std::size_t, typename>
struct iLH;

template <std::size_t N, std::size_t ... Is>
struct iLH<N, indexList<Is...>> : public iLH<(N >> 1), indexList<Is..., N>>
 { };

template <std::size_t ... Is>
struct iLH<0U, indexList<Is...>>
 { using type = indexList<Is...>; };

template <std::size_t N>
struct getIndexList : public iLH<N, indexList<>>
 { };

template <std::size_t N>
using getIndexList_t = typename getIndexList<N>::type;
template <std::size_t N>
class Foo
 {
   private:
      const std::vector<char **> bar = bar_init (getIndexList_t<N>{});

      template <std::size_t ... Is>
      static std::vector<char **> bar_init (indexList<Is...> const &)
       {
         std::vector<char **> init { MyClass<char(*)[Is]>::getPtr()... };

         return init;
       }
 };
template <typename T>
struct MyClass;

template <std::size_t Dim>
struct MyClass<char(*)[Dim]>
 {
   static char ** getPtr ()
    { static char ach[Dim]; static char * ret { ach } ; return &ret; }
 };

template <std::size_t ...>
struct indexList
 { };

template <std::size_t, typename>
struct iLH;

template <std::size_t N, std::size_t ... Is>
struct iLH<N, indexList<Is...>> : public iLH<(N >> 1), indexList<Is..., N>>
 { };

template <std::size_t ... Is>
struct iLH<0U, indexList<Is...>>
 { using type = indexList<Is...>; };

template <std::size_t N>
struct getIndexList : public iLH<N, indexList<>>
 { };

template <std::size_t N>
using getIndexList_t = typename getIndexList<N>::type;

template <std::size_t N>
class Foo
 {
   private:
      const std::vector<char **> bar = bar_init (getIndexList_t<N>{});

      template <std::size_t ... Is>
      static std::vector<char **> bar_init (indexList<Is...> const &)
       {
         std::vector<char **> init { MyClass<char(*)[Is]>::getPtr()... };

         return init;
       }
 };

int main ()
 {
   Foo<32U>  f32;
 }