template<typename T> constexpr inline
T getClamped(const T& mValue, const T& mMin, const T& mMax)
{
assert(mMin < mMax); // remove this line to successfully compile
return mValue < mMin ? mMin : (mValue > mMax ? mMax : mValue);
}
Run Code Online (Sandbox Code Playgroud)
错误:constexpr函数的主体 'constexpr T getClamped(const T&,const T&,const T&)[with T = long unsigned int]' not return-statement
用g++ 4.8.1.clang++ 3.4不抱怨
谁在这?我可以g++在不使用宏的情况下编译代码吗?
如果声明了一个对象const,则保证其值仅在运行时可用,但如果声明constexpr了该值,则保证该值在编译期间和运行时都可用.因此,如果我有一个在编译期间值可用的对象,是否有任何我不应该声明它的情况constexpr?
const int magicValue = 42; // Does this ever make sense
// (using const instead of constexpr)?
Run Code Online (Sandbox Code Playgroud)
对于函数,如果函数可以返回编译期间计算的值,当在编译期间传递带有值的参数时,是否有意义不声明函数constexpr?
struct Point { int x; int y; };
Point midPoint(Point p1, Point p2) // Does this ever make
{ // sense (not declaring
return { (p1.x + p2.x) / 2 , (p1.y + p2.y) / 2 }; // the function
} // constexpr)?
Run Code Online (Sandbox Code Playgroud)
我能想到的唯一情况是当你不想提交能够在使用known-at-compile-time参数调用时计算编译时常量的函数,例如,如果你想保持灵活性改变midPoint实现而不改变其界面(从而可能破坏调用者).例如,您可能希望保留将非constexpr副作用添加到midPoint例如IO 的灵活性.
struct A {
int a = 0;
constexpr A() { a = 1; }
};
constexpr bool f() {
constexpr A a;
static_assert(a.a == 1, ""); // L1: OK
return a.a == 1;
}
static_assert(f(), ""); // L2: Error, can not modify A::a in constexpr
Run Code Online (Sandbox Code Playgroud)
如果我删除L2,则此代码编译.如果我添加L2,编译器抱怨"在常量表达式中不允许修改const限定类型的对象'const int'".我不是语言律师,所以我不确定这是否属实.但是,如果是,为什么编译器没有抱怨任何关于L1的东西,因为它也称为A()为constexpr?这是一个铿锵的错误吗?或者我错过了什么?
参考:http://en.cppreference.com/w/cpp/language/constexpr
顺便说一句,如果我改变"constexpr A a;" 到"A a;" (删除constexpr关键字),L1无法编译,这是期望的.但是,编译器不再抱怨L2了.
关于此的在线编译器URL:http://goo.gl/AoTzYx
无论如何配置constexpr实例化深度?我正在运行-fconstexpr-depth = 4096(使用clang/XCode).
但仍然无法编译此代码并出现错误:Constexpr变量fib_1必须由常量表达式初始化.无论是否设置了选项-fconstexpr-depth = 4096,代码都会失败.
这是clang的错误还是预期会以这种方式运行.注意:这在fib_cxpr(26)之前有效,27是在它开始失败时.
码:
constexpr int fib_cxpr(int idx) {
return idx == 0 ? 0 :
idx == 1 ? 1 :
fib_cxpr(idx-1) + fib_cxpr(idx-2);
}
int main() {
constexpr auto fib_1 = fib_cxpr(27);
return 0;
}
Run Code Online (Sandbox Code Playgroud) 假设我有一个可以通过constexpr函数返回常量表达式的类:
template<int N>
struct Foo {
constexpr int Bar() const { return N; }
};
Run Code Online (Sandbox Code Playgroud)
如果我想初始化constexpr值Foo::Bar(),我应该如何传递类型的参数Foo?我已经尝试了这两个,constexpr每个都有一个示例变量来测试它是否可以初始化:
template<int N>
constexpr int ByValue(Foo<N> f) {
constexpr int i = f.Bar();
return f.Bar();
}
template<int N>
constexpr int ByReference(const Foo<N> &f) {
constexpr int i = f.Bar();
return f.Bar();
}
constexpr int a = ByValue(Foo<1>{});
constexpr int b = ByReference(Foo<1>{});
Run Code Online (Sandbox Code Playgroud)
但是clang 3.7引发了一个错误,ByReference而gcc> = 5.1则没有:现场演示
main.cpp:15:25: error: constexpr variable 'i' must be initialized …Run Code Online (Sandbox Code Playgroud) 给出以下代码:
struct f {
};
int main(){
constexpr f f1 ;
//const f f1 ; // This also has the same issue
//constexpr f f1 = {} ; //This works
}
Run Code Online (Sandbox Code Playgroud)
clang和gcc不同意它是否有效,clang提供以下诊断(见现场直播):
error: default initialization of an object of const type 'const f' without a user-provided default constructor
constexpr f f1 ;
^
{}
Run Code Online (Sandbox Code Playgroud)
据我所知f,它是一个文字类型,它由隐式默认的构造函数初始化,它应该允许它被声明为constexpr.谁在这里是对的?
注意,f1如果我显式添加constexpr默认构造函数,则clang会接受声明:
constexpr f() {} ;
Run Code Online (Sandbox Code Playgroud)
答案变化f是不是聚合?
应该不是的std ::调用是constexpr特别是在C++中17 constexpr lambda表达式?
是否有任何阻碍这种情况的障碍?
下面的代码使用gcc和MSVC进行编译,但是使用clang我用clang-3.5和当前主干测试失败了.
template <typename T>
constexpr auto wrong = false;
template <typename T>
constexpr auto foo(const T t) -> int
{
static_assert(wrong<T>, "");
return {};
}
using F = decltype(foo(1));
int main() {}
Run Code Online (Sandbox Code Playgroud)
clang实例化函数体并绊倒了static_assert.gcc和MSVC只是查看函数声明并忽略static_assert正文.
如果删除constexpr,所有编译器都可以编译代码.
问题:
如果声明了返回类型,是否允许decltype查看函数体?
我正在寻找标准中相应部分的参考.
这个问题似乎与现有问题有关,但我不理解答案中提供的"便携式解决方法" (涉及const auto this_ = this;),而且我认为以下示例更容易理解.
我正在使用以下C++ 17代码片段(现场演示):
#include <iostream>
struct Test {
const char* name_{nullptr};
const Test* src_{nullptr};
constexpr Test(const char* name) noexcept
: name_{name}
{}
constexpr Test(const Test& src) noexcept
: src_{&src}
{
name_ = src_->name_;
src_ = nullptr;
}
};
template<char c>
void print_constexpr_char() {
std::cout << c << std::endl;
}
int main() {
constexpr const char* in = "x";
constexpr auto foo = Test{in};
constexpr auto bar = …Run Code Online (Sandbox Code Playgroud) 这段代码用clang和gcc编译得很好.
template<size_t n>
struct N {
static constexpr size_t v = n;
};
template<size_t n>
constexpr bool operator<(N<n>, size_t n2) {
return n < n2;
}
template<typename N>
constexpr void foo(N v) {
static_assert(v < 5);
}
int main()
{
foo(N<3>{});
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我使用MSVC,我得到的错误v < 5不是常量表达式.我能理解为什么MSVC会这么想,但我认为这是错误的,而clang/gcc是对的.这是来自MSVC的错误吗?