这是我想要做的简化版本.
constexpr float f(float a, float b){
constexpr float temp = a+b;
return temp*temp*temp;
}
Run Code Online (Sandbox Code Playgroud)
在我的版本中,a + b更复杂,所以我不想剪切和粘贴三次.使用3*(a + b)也不是实际功能的有效解决方案.我试图保持与语法相关的问题,而不是代数.我可以通过将+ b移动到它自己的constexpr函数来实现它,但我宁愿不用其他无用的函数来污染命名空间.
考虑以下简单的类X和类模板Y<T>,每个模板定义四个constexpr成员,其中三个具有推导的返回类型(新的C++ 1y特性),另外三个子集使用另一个新的C++ 1y特性:轻松constexpr现在也可以有副作用和void返回类型的功能.
下面是一个与这些功能相互作用的小实验:
#include <type_traits>
#include <utility>
struct X
{
constexpr void fun() {} // OK
constexpr auto gun() {} // OK
auto hun() {} // OK
constexpr auto iun() { return 0; } // OK
};
template<class T>
struct Y
{
constexpr void fun() {} // OK
//constexpr auto gun() {} // ERROR, why?
auto hun() {} // OK
constexpr auto iun() { return 0; } // OK …Run Code Online (Sandbox Code Playgroud) 我最近在这里问了一个问题(用SFINAE检测实例方法constexpr),我试图在编译时进行一些constexpr检测.最后,我发现可以利用noexcept这个来做:任何常量表达式也是如此noexcept.所以我把以下机器放在一起:
template <class T>
constexpr int maybe_noexcept(T && t) { return 0; }
...
constexpr bool b = noexcept(maybe_noexcept(int{}));
Run Code Online (Sandbox Code Playgroud)
这是正常的,b正如您所期望的那样,因为零初始化int是一个常量表达式.它应该正确地产生零(如果我改为int其他适当的类型).
接下来,我想检查某些东西是否可constexpr移动构造.所以我这样做了:
constexpr bool b = noexcept(maybe_noexcept(int(int{})));
Run Code Online (Sandbox Code Playgroud)
而且,这适用于int或用户定义的类型.但是,这会检查该类型是否包含constexpr默认构造函数和constexpr移动构造函数.所以,为了解决这个问题,我尝试改为declval:
constexpr bool b = noexcept(maybe_noexcept(int(declval<int>())));
Run Code Online (Sandbox Code Playgroud)
这导致在bgcc 5.3.0 中为false(不能使用任何一个clang,因为clang不能正确地生成常量表达式noexcept).没问题,我说,一定是因为declval(有趣的是)没有标记constexpr.所以我写了自己的天真版本:
template <class T>
constexpr T&& constexpr_declval() noexcept;
Run Code Online (Sandbox Code Playgroud)
是的,与标准库的工作方式相比,这是天真的,因为它会阻塞虚空和可能的其他东西,但它现在很好.所以我再试一次:
constexpr bool b = noexcept(maybe_noexcept(int(constexpr_declval<int>())));
Run Code Online (Sandbox Code Playgroud)
这仍然不起作用,b总是假的.为什么这不被视为常数表达式?这是一个编译器错误,还是我不了解基本原理constexpr?似乎在constexpr和未评估的上下文之间存在一些奇怪的交互.
作为一个实验,我只是将一些代码放在一起,以便std::array<uint32_t, 256>在编译时生成.表内容本身是一个相当典型的CRC查找表 - 关于唯一新的事情是使用constexpr函数来计算条目而不是将自动生成的魔术表直接放在源代码中.
无论如何,这个练习让我很好奇:编译器constexpr在编译时评估函数或变量定义的计算量是否会有任何实际限制?例如,像gcc的-ftemplate-depth参数一样,对模板元编程评估的数量创建实际限制.(我也想知道参数包的长度是否存在实际限制 - 这将限制std::array使用std::integer_sequence中间对象创建的编译时的大小.)
来自这个问题: 如何构建自定义宏,用作constexpr(如assert)时,其行为会有所不同?
我想知道如果有条件的话为什么可以调用非constexpr函数。
void bla( )
{
std::cout << "bla called!" << std::endl;
}
constexpr bool check(bool condition)
{
//bla(); // can not directly be called -> not constexpr!
condition ? void (0) : bla(); // compiles and runs even if condition is true or false!
// if condition is const, it did not compile because it
// directly force execution of non constexpr function
true ? void(0): bla(); // also that compiles!, ok, directly evaluated
//true ? bla(): void(0); …Run Code Online (Sandbox Code Playgroud) 对于模糊的标题感到抱歉,但我无法想出一个更好的标题.
我写了一个扁平化容器的函数:
template <typename Container, typename OutIt>
void flatten(const Container& container, OutIt res)
{
if constexpr (std::is_convertible_v<typename Container::value_type, typename std::iterator_traits<OutIt>::value_type>)
{
for (const auto& value : container)
{
*res = value;
++res;
}
}
else
{
for (const auto& subContainer : container)
flatten(subContainer, res);
}
}
Run Code Online (Sandbox Code Playgroud)
我希望它像以下一样使用:
vector<vector<int>> test = {{1}, {2, 3, 4}, {5, 6}, {7}};
vector<int> res;
flatten(test, std::back_inserter(res));
Run Code Online (Sandbox Code Playgroud)
这应该基本上是从复制所有嵌套值test到res,这样res == { 1, 2, 3, 4, 5, 6, 7 }.
但是,如果我想编译代码,编译器会抛出一些错误,基本上说,else …
我想编写一个constexpr模板函数来置换作为参数传入的数组元素.所以我想出了这样的事情:
template <typename T, std::size_t N, typename... Ts>
constexpr std::array<T, N> permute(const std::array<T, N>& arr, const std::array<int, N>& permutation, Ts&&... processed)
{
return (sizeof...(Ts) == N) ?
std::array<T, N>{ std::forward<Ts>(processed)... } :
permute(arr, permutation, std::forward<Ts>(processed)..., arr[permutation[sizeof...(Ts)]]);
}
Run Code Online (Sandbox Code Playgroud)
用法示例:
constexpr std::array<int, 3> arr{ 1, 2, 3 };
constexpr std::array<int, 3> permutation{ 2, 1, 0 };
constexpr auto result = permute(arr, permutation); //result should contain { 3, 2, 1 }
Run Code Online (Sandbox Code Playgroud)
问题是上面的代码没有编译.出于某种原因,g ++ 6.4尝试在"已处理"模板参数包下隐藏4个或更多参数来实例化置换模板.你能帮我纠正我的代码并让它编译吗?
我在头文件中有以下代码,它包含在2个不同的cpp文件中:
constexpr int array[] = { 11, 12, 13, 14, 15 };
inline const int* find(int id)
{
auto it = std::find(std::begin(array), std::end(array), id);
return it != std::end(array) ? &*it : nullptr;
}
Run Code Online (Sandbox Code Playgroud)
然后我调用find(13)每个cpp文件.将两个指针返回find()指向内存中的同一地址吗?
我问的原因是因为我的项目中有类似的代码,有时它可以工作,有时则不然.我假设两个指针都指向同一个位置,但我并没有真正有这个假设的基础:)
在C++ 11中,成员函数上的constexpr意味着const.这在C++ 14中有所改变.
我有一些代码,其成员函数应该是constexpr,但不能是const,所以如果用std c ++ 14或更高版本编译,我希望它是constexpr.一种方法是:
class Foo {
#if _cplusplus >= 201402L
constexpr
#endif
int baz(const Bar& bar);
};
Run Code Online (Sandbox Code Playgroud)
是否有更好的方式表达这一点,最好没有预处理器?
此代码编译:
struct Info
{
constexpr Info(bool val) : counted(false), value(unsigned(val)) {}
constexpr Info(unsigned val) : counted(true), value(val) {}
bool counted;
unsigned value;
};
constexpr const auto data = std::array{
Info{true}, Info{42u}
};
struct Foo
{
constexpr static inline const auto data = std::array{
Info{true}, Info{42u}
};
};
Run Code Online (Sandbox Code Playgroud)
此代码不会:
struct Foo
{
struct Info
{
constexpr Info(bool val) : counted(false), value(unsigned(val)) {}
constexpr Info(unsigned val) : counted(true), value(val) {}
bool counted;
unsigned value;
};
constexpr static inline const auto data = …Run Code Online (Sandbox Code Playgroud)