以下在GCC中编译,但在Clang中不编译:
#include <cstring>
constexpr int test = strcmp("test", "test");
Run Code Online (Sandbox Code Playgroud)
所以我的问题是,GCC如何以不同的方式处理strcmp才能做到这一点?是strcmp是某种内置类型,还是标准库具有包含constexpr的非标准strcmp定义?
GCC并Clang编译以下代码:
void Test()
{
constexpr int Size = 3;
auto Lambda = [Size]{ int Dim[Size]; };
}
Run Code Online (Sandbox Code Playgroud)
但是,VisualStudio 2015 CTP 6没有.尽管如此,所有3个编译器都对此代码感到满意:
void Test()
{
static constexpr int Size = 3;
auto Lambda = []{ int Dim[Size]; };
}
Run Code Online (Sandbox Code Playgroud)
哪个片段实际上是以正确的方式进行的?C++标准说什么?
考虑这个经典的例子:
template <typename T, std::size_t N>
constexpr std::size_t arraySize(T (&array)[N]) noexcept { return N; }
Run Code Online (Sandbox Code Playgroud)
现在这个工作正常,但有一个烦恼,gcc发出警告:
warning: unused parameter ‘array’ [-Wunused-parameter]
Run Code Online (Sandbox Code Playgroud)
已知解决方案:
(void)arr;到函数中,我会得到error: body of constexpr function ‘...‘ not a return-statement.arraySize(T (&)[N]),但我想说出这个论点有两个原因:
return sizeof(array)/sizeof(array[0]);,但这种方法不是通用的解决方案,而且我认为return N;更好,绝对更容易.{ (void)array; return N; }允许constexpr函数体.在使用C++ 11时,如何很好地消除未使用的参数警告?
constexpr和union我一起玩,我发现我不能更改unionin的活动成员constexpr。唯一的例外:union空类。
constexpr bool t()
{
struct A {};
struct B {};
union U { A a; B b; } u{};
u.a = A{};
u.b = B{};
return true;
}
static_assert(t());
constexpr bool f()
{
struct A { char c; };
struct B { char c; };
union U { A a; B b; } u{};
u.a = A{};
u.b = B{}; // error originating from here
return true;
}
static_assert(f());
Run Code Online (Sandbox Code Playgroud)
第一个函数可能会产生常量表达式。但是第二个不能。硬错误说: …
以下程序给出了链接时错误:
#include <iostream>
struct Test { static constexpr char text[] = "Text"; };
int main()
{
std::cout << Test::text << std::endl; // error: undefined reference to `Test::text'
}
Run Code Online (Sandbox Code Playgroud)
错误消息是
/tmp/main-35f287.o: In function `main':
main.cpp:(.text+0x4): undefined reference to `Test::text'
main.cpp:(.text+0x13): undefined reference to `Test::text'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Run Code Online (Sandbox Code Playgroud)
好.让我们试着解决这个问题:我在struct体外添加一个定义:
#include <iostream>
struct Test { static constexpr char text[] = "Text"; };
constexpr char Test::text[] = "Text";
int main()
{ …Run Code Online (Sandbox Code Playgroud) (使用g++ 7.0trunk.)
鉴于以下"类型到价值包装"实用程序......
template <typename T>
struct type_wrapper { using type = T; };
// "Wraps" a type into a `constexpr` value.
template <typename T>
constexpr type_wrapper<T> type_c{};
Run Code Online (Sandbox Code Playgroud)
...我创建了以下函数来检查表达式的有效性:
template <typename TF>
constexpr auto is_valid(TF)
{
return [](auto... ts) constexpr
{
return std::is_callable<TF(typename decltype(ts)::type...)>{};
};
}
Run Code Online (Sandbox Code Playgroud)
该is_valid功能可以使用如下:
// Evaluates to `true` if `some_A.hello()` is a valid expression.
constexpr auto can_add_int_and_float =
is_valid([](auto _0) constexpr -> decltype(_0.hello()){})
(type_c<A>);
// Evaluates to `true` if `some_int + some_float` is …Run Code Online (Sandbox Code Playgroud) 举个例子:
class something {
public:
static constexpr int seconds(int hour, int min, int sec)
{ return hour*3600+min*60+sec; }
}
Run Code Online (Sandbox Code Playgroud)
然后:
printf("Look at the time: %d\n", something::seconds(10, 0, 0));
Run Code Online (Sandbox Code Playgroud)
将编译为使用g ++调用函数,而不是使用常数.为什么g ++会这样做?它没有任何好处,有点挫败了使用constexpr而不是糟糕的宏的目的.
我有一个Config课程
// config.hpp
class Config {
public:
static constexpr int a = 1;
static constexpr int b = 1;
}
Run Code Online (Sandbox Code Playgroud)
并包含在main.cpp中
// main.cpp
#include "config.hpp"
int main () {
std::cout << Config::a << std::endl; // this is ok
std::shared_ptr<otherClass> stream = std::make_shared<otherClass>(
Config::a); // compile error
}
Run Code Online (Sandbox Code Playgroud)
和编译器说 undefined reference to Config::a
它在使用时起作用cout,但在shared_ptr构造函数中不起作用.
我不知道为什么会这样.
我试图cons-cell用C++中的函数式编程语言模拟列表结构constexpr.我有一种pair类型,一开始.这是两个不同的东西的持有者,但也支持嵌套对.这是代码.
template <typename E1, typename E2>
struct pair {
constexpr pair()
:_car{E1{}}, _cdr{E2{}}
{}
constexpr pair(const E1 &car, const E2 &cdr)
:_car{car}, _cdr{cdr}
{}
constexpr auto car() const{
return _car;
}
constexpr auto cdr() const{
return _cdr;
}
friend std::ostream& operator<<(std::ostream& str,
pair<E1, E2> p){
if(p == pair{})
return str;
str << p.car() << " " << p.cdr();
return str;
}
template <typename Functor>
friend constexpr auto fmap(Functor f,
const pair<E1, E2> p){
if …Run Code Online (Sandbox Code Playgroud) 我正在使用一个API,它将带有单个参数的函数作为回调.回调采用某种类型的单个参数,为简单起见,我会说它返回一个bool.我试图整理的主要内容是范围检查功能.我的直觉是写这样的东西:
template<class T, T min, T max>
constexpr bool in_range(T val) {
return (val >= min && val <= max);
}
static_assert(in_range<float, 0.0f, 1.0f>(0.5f), "doesn't work")
Run Code Online (Sandbox Code Playgroud)
但是,这不起作用,所以我默认以这种方式创建一个函数.
template<class T>
std::function<bool(T)> in_range(T min, T max) {
auto test = [min, max](T val) {
return (val >= min && val <= max);
};
return test;
}
assert(in_range<float>(0.0f, 1.0f)(0.5f))
Run Code Online (Sandbox Code Playgroud)
有没有办法以第一个函数的形式更多地编写函数,所以我不依赖std::function于运行时生成的lambdas?