template< int array_qty > class sample_class { public: std::array< std::string,array_qty > sample_array; }
如果我这样做,它的工作原理:
sample_class< 10 > sample_class_instance;
但是,让我说在编译时我不知道array_qty(模板参数)的值,并且只会在运行时知道它.在这种情况下,我基本上将传递一个int变量作为模板参数.为了演示,以下代码不起作用:
int test_var = 2; int another_test_var = 5; int test_array_qty = test_var * another_test_var; sample_class< test_array_qty > sample_class_instance;
尝试上述操作时,在编译期间出现以下错误:
the value of ‘test_array_qty’ is not usable in a constant expression
我已经尝试将test_array_qty转换为const,同时将其作为模板参数传递,但这似乎也没有.有没有办法做到这一点,还是我滥用模板参数?也许他们需要在编译时知道?
目标不是解决这个特定的方法,而是找到一种方法将数组的长度设置为一个int变量,可以在实例化类时声明.如果有办法通过模板参数执行此操作,那将是理想的.
请注意,我必须使用一个数组,而不是我最终可能作为建议的向量.此外,array_qty将始终是0到50之间的值 – 如果有所不同.
编辑:
我声明我不能使用矢量,因为我不能使用这个矢量.是的,我对它进行了基准测试.无论哪种方式,这个问题不是对“数组与向量”的探索.我想避免这个问题有很多评论和答案告诉我“只使用矢量”.这有点像向爱迪生说“只是用蜡烛”.良好的编程是对可能性的探索,而不仅仅是对已知内容的陈述.如果我们由于纯粹的不可能性而无法弄清楚这一点,那就是一回事.没有探索解决这个问题的可能性,因为“矢量会更容易”不是.
另外,我不明白为什么会有这个问题.这是一个完整有效的问题,以一致的方式提出.
解决方法
你实际可以做的是创建50个不同的程序,50个可能的大小中的每一个,然后有条件地跳转到你想要的程序.
template<int n> struct prog { void run() { // ... } }; template<int n> struct switcher { void run(int v) { if(v==n) prog<n>::run(); else switcher<n-1>::run(v); } }; template<> struct switcher<-1> { void run(int v){ } };
呼叫切换器< 50> :: run(value);如果value为0到50,则调用prog< value> :: run().在prog :: run中,template参数是编译时值.
可怕的黑客,你可能会更好地使用另一种解决方案,但这是你要求的.
这是一个基于C 14表格的版本:
template<size_t N> using index_t = std::integral_constant<size_t,N>; // C++14 template<size_t M> struct magic_switch_t { template<class...Args> using R=std::result_of_t<F(index_t<0>,Args...)>; template<class F,class...Args> R<Args...> operator()(F&& f,size_t i,Args&&...args)const{ if (i >= M) throw i; // make a better way to return an error return invoke(std::make_index_sequence<M>{},std::forward<F>(f),i,std::forward<Args>(args)...); } private: template<size_t...Is,class F,class...Args> R<Args...> invoke(std::index_sequence<Is...>,F&&f,Args&&...args)const { using pF=decltype(std::addressof(f)); using call_func = R<Args...>(*)(pF pf,Args&&...args); static const call_func table[M]={ [](pF pf,Args&&...args)->R<Args...>{ return std::forward<F>(*pf)(index_t<Is>{},std::forward<Args>(args)...); }... }; return table[i](std::addressof(f),std::forward<Args>(args)...); } };
magic_switch_t< N> {}(f,3,blah1,blah2等)将调用f(index_t< 3> {},blah2等).
一些C 14编译器会阻塞包含lambda的变量包扩展.这不是必需的,你可以做一个解决方法,但解决方法是丑陋的.
C 14的功能都是可选的:你可以在C 11中实现它,但又一次,丑陋.
传递的f基本上应该是一个函数对象(lambda将auto作为第一个参数,或者是手动的).直接传递函数名称将无法正常工作,因为当第一个参数成为编译时值时,上述最佳方法有效.