我正在使用一个库来公开要使用的接口。这个库的一个功能是这样的:
template <int a>
void modify(){}
我必须修改1到10之间的参数,即使用模板参数从1到10调用modify
。为此,我编写了这段代码(代码的基本版本,实际代码要大得多)。
for(int i=0; i<10; i++){
modify<i>();
}
编译时收到以下错误
error: 'i' cannot appear in constant-expression
通过互联网上的一些链接后,我发现我无法传递任何值作为模板参数,而这些参数在编译时未被评估。
我的问题如下:
1.为什么编译时编译器不能评估i
?
2.还有其他任何方法可以实现我想要在不改变API接口的情况下实现的目标吗?
还有一件事我想做。调用修改为修改,其中VAR是某些功能计算的输出。我怎样才能做到这一点?
答案 0 :(得分:28)
编译时 i (不是常量)的值是多少?除非执行循环,否则无法回答。但执行不是&#34;编译&#34; 由于没有答案,编译器不能这样做。
模板不是要执行的算法,而是要扩展以生成代码的宏。 你可以做的是依靠专门化来通过递归来实现迭代,就像这里:
#include <iostream>
template<int i>
void modify()
{ std::cout << "modify<"<<i<<">"<< std::endl; }
template<int x, int to>
struct static_for
{
void operator()()
{ modify<x>(); static_for<x+1,to>()(); }
};
template<int to>
struct static_for<to,to>
{
void operator()()
{}
};
int main()
{
static_for<0,10>()();
}
请注意,通过这样做,您实际上是在实例化10个名为的函数
modify<0>
... modify<9>
,分别由static_for<0,10>::operator()
... static_for<9,10>::operator()
调用。
迭代结束是因为static_for<10,10>
将从具有两个相同值的特化中实例化,而不执行任何操作。
答案 1 :(得分:3)
由于您使用Boost.MPL要求答案:
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/range_c.hpp>
#include <iostream>
template <int N>
void modify()
{
std::cout << N << '\n';
}
// You need to wrap your function template in a non-template functor
struct modify_t
{
template <typename N>
void operator()(N)
{
modify<N::value>();
}
};
int main()
{
namespace mpl = boost::mpl;
mpl::for_each< mpl::range_c<int,0,10> >( modify_t() ); // prints 0 to 9
}
答案 2 :(得分:2)
“为什么编译时编译器不能评估i
?”
这会破坏模板的目的。模板适用于某些情况下源代码看起来相同的情况,但编译器每次生成的指令都不同。
“还有其他方法可以实现我想要实现的目标,而无需更改API接口吗?”
是的,请看Boost.MPL。
但我怀疑这里的正确答案是您要更改API。这取决于modify
函数的内部。我知道你有它的来源,因为模板必须在标题中定义。因此,看看为什么它需要在编译时知道i
,如果没有,最好用带参数的普通函数替换(或补充,如果你需要保持向后兼容性)。
答案 3 :(得分:1)
不使用 struct 或 Boost ,也可以这样做:
#include <iostream>
#include <utility>
template <int a>
void modify()
{
std::cout<<a<<",";
}
template<int i,size_t... t>
constexpr inline void CT_for_impl(std::integer_sequence<size_t,t...>)
{
bool kai[]= { (modify<i+t>(), false)...};
}
template<int i,int n>
constexpr inline void CT_for()
{
CT_for_impl<i>(std::make_index_sequence<n-i+1>());
}
int main()
{
CT_for<-5,5>();
return 0;
}
答案 4 :(得分:1)
错误解决方案:&#39;我&#39;对于上述问题,不能出现在常量表达式中
To read about constexpr click this link
FileReader.readAsArrayBuffer
答案 5 :(得分:0)
鉴于您希望通过索引在运行时调用这些函数而无法更改API,您可以考虑使用类型擦除:
std::vector<std::function<void(int)> > func;
func.push_back(modify<1>);
func.push_back(modify<2>);
//... and so on ...
func.push_back(modify<10>);
for(int i=0; i<10; ++i)
{
func[i](); //calls modify<i+1>();
}
有些要点:
modify<7>()
将返回,例如,std::string
整个方法将会中断)。 push_back
包装到另一个迭代静态函数中以避免手动调用。