c++ 11 constexpr函数传递参数
C++11 constexpr function pass parameter
考虑以下代码:
static constexpr int make_const(const int i){
return i;
}
void t1(const int i)
{
constexpr int ii = make_const(i); // error occurs here (i is not a constant expression)
std::cout<<ii;
}
int main()
{
t1(12);
}
为什么我有一个错误的make_const调用?
但是这个可以:
constexpr int t1(const int i)
{
return make_const(i);
}
但是,这不是:
template<int i>
constexpr bool do_something(){
return i;
}
constexpr int t1(const int i)
{
return do_something<make_const(i)>(); // error occurs here (i is not a constant expression)
}
一个constexpr
函数和一个constexpr
变量是相关的,但是不同的东西。
constexpr
变量是一个变量,它的值保证在编译时可用。
constexpr
函数是一个函数,如果用constexpr
参数求值,和行为"正确";在执行过程中,将在编译时求值。
如果将非constexpr
int
传递给constexpr
函数,它不会在编译时神奇地使其求值。然而,它将被允许通过自身传递其输入参数的constexpr
性(普通函数不能这样做)。
关于函数的constexpr
是关于如何编写函数的文档和限制以及对编译器的指令的混合。
这样做的原因是允许在编译时和运行时对同一个函数求值。如果传递了运行时参数,它就是一个运行时函数。如果传递了constexpr
参数,则可以在编译时对其求值(如果在某些上下文中使用,则会这样做)。
请注意,consteval
可能是您正在寻找的函数。但也许不是。
你得到错误,因为通过传递运行时值,你不能得到编译时值。
有很多方法可以解决这个问题。我最喜欢的是std::integer_constant
的std::variant
;您可以选择哪个在运行时是活动的,然后选择std::visit
以获得编译时间常数。缺点是这样可以很容易地生成大量代码。
template<auto I>
using constant_t=std::integral_constant<decltype(I),I>;
template<auto I>
constexpr constant_t<I> constant_v={};
template<auto...Is>
using var_enum_t=std::variant<constant_t<Is>...>;
template<class Indexes>
struct var_enum_over;
template<class Indexes>
using var_enum_over_t=typename var_enum_over<Indexes>::type;
template<class T,T...ts>
struct var_enum_over<std::integral_sequence<T,Is...>>{
using type=var_enum_t<Is...>;
};
template<std::size_t N>
using var_index_t=var_enum_over_t<std::make_index_sequence<N>>;
template<std::size_t N>
var_index_t<N> var_index(std::size_t I){
constexpr auto table=[]<std::size_t...Is>(std::index_sequence<Is...>)->std::array<N,var_index_t<N>>{
return { var_index_t<N>(constant_v<Is>)..., };
}(std::make_index_sequence<N>{});
if (I>=N) throw 0; // todo: something better
return table[I];
}
(可能有拼写错误)。
现在你可以:
auto idx=var_index<5>(3/* 3 can be runtime */);
std::visit([](auto three){
// three is a compile time value here
}, idx);
const
和constexpr
的一个重要区别是constexpr
可以在编译时求值。
通过写constexpr int ii = make_const(i);
,你告诉编译器表达式将在编译时求值。由于i
是在运行时求值的,编译器无法这样做,并给您一个错误。
因为t1()不是constexpr函数,所以参数i是运行时变量…它不能传递给constexpr函数。Constexpr期望参数在编译时是已知的。
- 将可变参数函数的参数封装在类实例中
- QML 使用带有参数C++函数
- 使用可变参数函数作为模板参数
- 如何在C++中伪造虚拟可变参数函数模板?
- 为什么可变参数函数不适用于模板
- C++ std::functional 中的可变参数函数模板
- 可变参数函数指针的定义对于VxWorks spyLib来说不清楚
- 使用可变参数函数覆盖具有不同函数签名的虚函数
- 考虑引用和常量的可变参数函数包装器
- 使用可变参数函数将整数和/或整数数组放入单个 int 数组中
- 在可变参数函数中转发特定范围的参数
- 通过引用传递参数;函数返回类型是否必须为 VOID?
- 使用带有一个参数函数的递归找到数字的平方
- 可变参数函数模板不能很好地使用 std::function 作为参数
- 多个可变参数函数的单个模板参数包?
- 参数数据类型未知的可变参数函数
- 可变参数函数参数包扩展
- 使用模板可变参数函数将多个参数传递给另一个函数
- 对可变参数函数的递归调用的链接器错误
- 通过像printf这样的可变参数函数传递一个带有常量字符*转换函数的类