将变量作为模板参数传递
Passing a variable as a template argument
我正在使用一个公开接口的库。这个库的功能之一是这样的:
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 是某些函数计算的输出。我该怎么做?
编译时 i(不是常量)的值是多少?除非执行循环,否则无法回答。但执行不是"编译"由于没有答案,编译器无法这样做。
模板不是要执行的算法,而是要扩展以生成代码的宏。你可以做的是依靠专业化通过递归来实现迭代,如下所示:
#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>
将从采用两个相同值的专用化中实例化,而不执行任何操作。
-
"为什么编译器不能在编译时计算
i
?"这将破坏模板的目的。模板适用于源代码在某些情况下看起来相同的情况,但编译器每次需要生成的指令都不同。
-
"有没有其他方法可以在不更改 API 接口的情况下实现我想要实现的目标?"
是的,看看Boost.MPL。
但是,我怀疑这里的正确答案是您要更改API。这取决于
modify
函数的内部结构。我知道你有它的源代码,因为模板必须在标题中定义。所以看看为什么它在编译时需要知道i
,如果没有,最好用带有参数的正常函数替换(或补充,如果你需要保持向后兼容性)。
既然你使用 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
}
不使用 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;
}
如果您想在运行时通过函数的索引调用函数,并且无法更改 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
包装到另一个迭代静态函数中,以避免手动调用。
错误的解决方案:"i"不能出现在上述问题的常量表达式中
要阅读有关constexpr的信息,请单击此链接
#include <iostream>
using namespace std;
template <typename T>
void modify(T a)
{
cout<<a<<endl; //to check if its working
}
//func converts int a into const int a
constexpr int func(int a)
{
return a;
}
int main(){
for(int i=0; i<10; i++){
modify(func(i));//here passing func(i) returned value which can be used as template argument now as it is converted to constexpr
}
return 0;
}
- 如何将指针变量作为引用参数传递?
- 变量模板是否可以作为模板模板参数传递
- 是否可以将结构的成员变量作为参数传递
- C++:访问作为函数参数传递的双指针数组所指向的变量的值
- 在 c++ 模板中将变量作为参数传递
- 是否可以将变量/函数返回作为模板参数传递
- 有什么理由C++ 11+ std::mutex 应该声明为全局变量,而不是作为函数参数传递到 std::thread 中
- 如何在C++中接收任何类型的函数参数并获取函数内传递变量的类型?
- 如何将变量作为构造函数参数或函数参数传递
- 让宏将迭代参数传递到通过宏变量提供的代码体中
- 即将将引用作为函数中的参数传递以更改参数变量的值
- 是否可以在不为该数组创建变量的情况下将数组作为参数传递到函数中?
- 当将变量作为函数参数传递时,由于隐式铸造而导致的精度丧失
- 如果结构作为递归函数中的参数传递,如何初始化结构的成员变量
- C 11-当我将局部变量作为参数传递到线程中时,它是否安全
- 如果我有一个将指针变量作为输入的函数,有没有办法将函数作为参数传递
- 为什么我无法访问作为参数传递到函数中的基类的受保护成员变量?
- 如何强制转换变量成员以将其作为函数的引用参数传递
- 直接访问成员变量或作为参数传递
- 将变量作为模板参数传递