我正在使用gcc 4.6.1并且正在获得一些涉及调用constexpr函数的有趣行为.这个程序运行得很好,直接打印出来12200160415121876738.
#include <iostream>
extern const unsigned long joe;
constexpr unsigned long fib(unsigned long int x)
{
return (x <= 1) ? 1 : (fib(x - 1) + fib(x - 2));
}
const unsigned long joe = fib(92);
int main()
{
::std::cout << "Here I am!\n";
::std::cout << joe << '\n';
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这个程序需要永远运行,我从来没有耐心等待它打印出一个值:
#include <iostream>
constexpr unsigned long fib(unsigned long int x)
{
return (x <= 1) ? 1 : (fib(x - 1) + …Run Code Online (Sandbox Code Playgroud) 你会替换吗?
const int one = 1;
const int two = 2;
Run Code Online (Sandbox Code Playgroud)
有了这个?
constexpr int one = 1;
constexpr int two = 2;
Run Code Online (Sandbox Code Playgroud)
我的理解是正确的,两个块在语义上是相同的,并且它目前只是一个品味的问题?
另一方面,正如constexpr所暗示的那样const,你可以争辩说,总是更喜欢更具限制性的形式更为一致,即使是在无关紧要的微不足道的情况下也是如此?
(我理解当右侧的表达式允许更复杂时,情况会完全改变.因此,为了澄清,问题只关注表达式是固定整数的最简单的情况.)
说我有
constexpr const std::uint8_t major = 1;
constexpr const std::uint8_t minor = 10;
constexpr const std::uint8_t bugfix = 0;
Run Code Online (Sandbox Code Playgroud)
而且我要
constexpr const char* version_string(){ ... }
Run Code Online (Sandbox Code Playgroud)
要返回"1.10.0"本例中的等价物,我该怎么做?
我假设我需要这两个,在constexpr:
这个问题纯粹是学术性的,constexpr除了"有可能"之外,我认为实际上没有任何用处.我只是看不出这会如何发展.我愿意接受适用于GCC 4.9和Clang 3.4/3.5的C++ 1y解决方案.
我相信我在日本的一些博客上发现了几乎所有的东西:
我会看到我能用这些做些什么,也许当我对结果感到满意时,我自己回答这个自称有趣的问题.
constexpr我的库中有几个简短的函数可以执行一些简单的计算.我在运行时和编译时上下文中都使用它们.
我想在这些函数的主体中执行一些断言,但是assert(...)在constexpr函数中无效并且static_assert(...)不能用于检查函数参数.
例:
constexpr int getClamped(int mValue, int mMin, int mMax) noexcept
{
assert(mMin <= mMax); // does not compile!
return mValue < mMin ? mMin : (mValue > mMax ? mMax : mValue);
}
Run Code Online (Sandbox Code Playgroud)
有没有办法检查函数是在运行时或编译时常量中执行还是assert只在运行时执行它才执行?
constexpr int getClamped(int mValue, int mMin, int mMax) noexcept
{
assert_if_runtime(mMin <= mMax);
return mValue < mMin ? mMin : (mValue > mMax ? mMax : mValue);
}
Run Code Online (Sandbox Code Playgroud) 这是我的工作代码示例:
#include <iostream>
template<typename B>
class b {
public:
int y;
constexpr b(int x) : y(x) {
}
constexpr void sayhi() {
std::cout << "hi" << std::endl;
}
};
template<int x>
struct A {
static constexpr b<int> bee = x;
static constexpr int y = x; // this one is fine and usable already, I don't have to do something like what I did on member bee
inline static void sayhi() {
std::cout << y << std::endl;
}
};
template<int …Run Code Online (Sandbox Code Playgroud) 我正在制定一个提出功能头功能的提议constexpr.(std::invoke,std::reference_wrapper,std::bind,std::mem_fn,std::not_fn)
我已经了解到添加constexpr可以破坏现有代码,因为constexpr函数是急切实例化的.
template<class T>
int f(T){
return T::not_existing_member;
}
template<class T>
constexpr int g(T){
return T::not_existing_member;
}
int main(){
decltype(f(0)) a; // Well-formed
decltype(g(0)) b; // Ill-formed if the function body is instantiated
}
Run Code Online (Sandbox Code Playgroud)
GCC编译这段代码,clang没有.我在我的提议中描述了如何使用示例来处理带有重载的急切实例化std::bind.
你能告诉我编译器必须在标准中描述的位置,以及何时允许实例化一个功能模板?
更确切地说,我想知道在以下示例中,GCC和clang的相同行为是由标准强制执行还是实现定义:
template<class T>
struct Foo{
constexpr int f(){
return 0;
}
constexpr int f()const{
return T::not_existing_member;
} …Run Code Online (Sandbox Code Playgroud) 是否有可能在C++中有这样的东西:
struct Foo
{
int x;
constexpr Foo(int x) : x(x) {}
static constexpr Foo table[] =
{
Foo(0),
Foo(1),
Foo(2),
};
};
Run Code Online (Sandbox Code Playgroud)
我尝试了几种组合,但都没有效果.如果table不是Foo类的一部分,它可以工作,但我真的希望它成为Foo命名空间的一部分.
编辑:
我想要这个的原因是我可以访问表格Foo::table.我在命名空间中有几个这样的类,如果我可以通过编写导入我正在使用的类using someNamespace::Foo然后访问该表,这非常方便Foo::table.如果表在课外,我必须始终通过写作来访问它someNamespace::fooTable.
我目前正在与Visual Studio 2017进行斗争(/std:c++latest如果有任何帮助,请编译使用).
有问题的代码只是根据一些模板化constexpr函数的结果选择结构特化.GCC和clang编译它没有问题.
这是我的MCVE:
#include <type_traits>
struct A {
enum {
test_trait = true
};
};
template<typename T>
constexpr int choose() {
return T::test_trait;
}
template<typename T, typename Enable=void>
struct Chosen;
template<typename T>
struct Chosen<T, std::enable_if_t<choose<T>() == 1>> {};
void foo() {
// This works
constexpr int chosen = choose<A>();
static_assert(chosen == 1, "");
// This resolves to the undefined struct.
using Chosen_t = Chosen<A>;
Chosen_t x;
(void)x;
}
Run Code Online (Sandbox Code Playgroud)
choose()在我的代码库中实际上有点复杂,但static_assert仍然编译,并检查正常.
我有点假设,如果static_assert …
我有一个带有int模板参数的类.在某些情况下,我希望它输出一条错误消息.此消息应该是来自某些固定文本和模板参数的串联字符串.出于性能原因,我希望每次发生错误时都避免在运行时构建此字符串,理论上两者都是,字符串文字和模板参数在编译时是已知的.所以我正在寻找将其声明为constexpr的可能性.
代码示例:
template<int size>
class MyClass
{
void onError()
{
// obviously won't work but expressing the concatenation like
// it would be done with a std::string for clarification
constexpr char errMsg[] = "Error in MyClass of size " + std::to_string (size) + ": Detailed error description\n";
outputErrorMessage (errMsg);
}
}
Run Code Online (Sandbox Code Playgroud) 根据某种条件在几个已知范围之一上进行迭代的最有效方法是什么?
二进制条件的伪代码:
for element in (condition ? range_a : range_b)
// do work
Run Code Online (Sandbox Code Playgroud)
这个“示例”显示了我使用基于范围的for循环的意图,但由于std::initializer_list具有参考语义,因此无法使用。
for element in (condition ? range_a : range_b)
// do work
Run Code Online (Sandbox Code Playgroud)
产量: warning: returning address of local temporary object [-Wreturn-stack-address]
在运行时,我可以返回a,std::vector但这将涉及在每次调用时构造一个新的向量:
constexpr auto some_range(bool c) -> std::initializer_list<int> {
if (c) {
return {1,2};
} else {
return {3, 4, 5};
}
}
bool cond = true; // false
for(auto x : some_range(cond)) {
// things
}
Run Code Online (Sandbox Code Playgroud)
我可以使用的固定大小std::array …