小编Dra*_*-On的帖子

检测编译时文字和常量

假设我想编写一个通用类,它维护一个始终保持在两个值之间的整数.像这样的东西:

template<int Lower, int Upper>
class MyInt {
    private:
        int m_int;
    public:
        // Constructors, operators...
};
Run Code Online (Sandbox Code Playgroud)

类不变量就是这样Lower <= m_int <= Upper.当然,MyInt应该具有整数所有的常用操作,比如赋值和算术运算符.如果操作将其置于打破其不变量的状态,MyInt将抛出.但是,在许多情况下,这应该是编译时可检测的.考虑这个示例代码:

int foo = 500;
constexpr int const bar = 500;
MyInt<0,100> a = 15; // OK
MyInt<0,100> b = foo; // Throws at runtime
MyInt<0,100> c = 500; // Compile error?
MyInt<0,100> d = bar; // Compile error?
MyInt<0,100> f = std::integral_constant<int, 500>; // Compile error
Run Code Online (Sandbox Code Playgroud)

因为std::integral_constant,编写适当的构造函数是直截了当的.但是,它可能编译时,检测a距离范围,c以及d有没有关系?指定的值是编译时已知的文字或constexpr常量.

我已经尝试了SFINAE-ing around和whatnot,但我找不到从值语义到模板参数的方法,即使对于这些情况,我声称这些值显然是编译时常量. …

c++ templates generic-programming c++17 c++20

8
推荐指数
2
解决办法
383
查看次数

高效的类型双关,没有未定义的行为

假设我正在开发一个名为 libModern 的库。该库使用称为 libLegacy 的遗留 C 库作为实现策略。libLegacy 的界面如下所示:

typedef uint32_t LegacyFlags;

struct LegacyFoo {
    uint32_t x;
    uint32_t y;
    LegacyFlags flags;
    // more data
};

struct LegacyBar {
    LegacyFoo foo;
    float a;
    // more data
};

void legacy_input(LegacyBar const* s); // Does something with s
void legacy_output(LegacyBar* s); // Stores data in s
Run Code Online (Sandbox Code Playgroud)

出于各种原因,libModern 不应该向用户公开 libLegacy 的类型,其中包括:

  • libLegacy 是一个不应泄露的实现细节。libModern 的未来版本可能会选择使用另一个库而不是 libLegacy。
  • libLegacy 使用难以使用、容易误用的类型,这些类型不应成为任何面向用户的 API 的一部分。

处理这种情况的教科书方法是 pimpl 习惯用法:libModern 将提供一个包装类型,该类型内部有一个指向遗留数据的指针。然而,这在这里是不可能的,因为 libModern 无法分配动态内存。一般来说,其目标不是增加大量开销。

因此,libModern 定义了自己的类型,这些类型与遗留类型布局兼容,但具有更好的接口。在此示例中,它使用强标志enum而不是普通uint32_t标志:

enum class ModernFlags : …
Run Code Online (Sandbox Code Playgroud)

c++ gcc language-lawyer type-punning c++20

8
推荐指数
1
解决办法
669
查看次数

基于可变参数模板的类成员变量

给定一个类型,名称和默认值的列表,我可以轻松编写一个生成有效c ++代码的工具,该代码声明一个具有每种类型,名称和默认值的成员变量的类.例如,给出列表

  • int,foo,42
  • 漂浮,酒吧,0.1f

(和类名"Baz"),它会生成

class Baz {
    int foo = 42;
    float bar = 0.1f;
}
Run Code Online (Sandbox Code Playgroud)

如果一个工具可以生成这样一个类,编译器不能为我做这个吗?我正在考虑这些方面的事情(注意:这是伪代码):

template <typename ...MemberTypes> class Baz {
    MemberTypes::type... MemberTypes::name... = MemberTypes::default...;
}
Run Code Online (Sandbox Code Playgroud)

上面的类将被创建类似的东西

using MyBaz = Baz<member_type<int, "foo", 42>, member_type<float, "bar", 0.1f>>;
Run Code Online (Sandbox Code Playgroud)

可能出现这种情况的原因:

  • 所有必需的信息都可在编译时获得.外部工具可以轻松完成.
  • 可以以类似的方式创建具有元组而不是专用成员变量的类(从variadic模板参数声明成员变量).
  • 我可以使用模板特化来近似成员的有限组合.
  • 模板元编程是图灵完备的(C++模板Turing-complete?),所以"一切"应该是可能的.

这可能是不可能的原因:

如果可以的话,怎么办呢?如果不可能,为什么不呢?即将到来的c ++ 17在这方面有什么改变吗?

更新:示例问题: 通常,配置数据存储为字符串的层次结构或某种其他形式的"任何类型".但是,这会导致丑陋的代码(config.get<int>("core.timeout"))并阻止编译器帮助解决,例如,typos(config.get<int>("core.timeuot")).

通过使用其真实类型声明每个配置变量,编译器可以检查类型并防止拼写错误.但是,需要使用自定义代码将配置数据读入正确的成员变量.如果添加了新配置开关,则很容易忘记更新此代码.

只需指定所有成员的类型和名称,然后让编译器自动生成类(包括读取配置文件的方法)将会很方便.这是我要求的功能的可能用例.

c++ templates template-meta-programming c++14 c++17

6
推荐指数
1
解决办法
1210
查看次数

在Travis CI上为C ++ 17设置Clang

我有一个小的C ++ 17项目,我想为其设置Travis CI。由于它是C ++ 17,因此需要现代编译器。我选择了gcc-7和clang-6。虽然gcc构建可以很好地编译和链接,但我一生都无法弄清楚如何正确设置clang。看起来它总是使用非常过时的预安装gcc的标准库实现,而不是它自己的。

travis日志显示以下行cmake --build . -- VERBOSE=1

/usr/bin/clang-6.0 -I / home / travis / build / myuser / perlin / include -g -std = gnu ++ 1z -o CMakeFiles / perlin.dir / main.cpp.o -c / home / travis /build/myuser/perlin/main.cpp

在/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/algorithm包含的文件中:62:在/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/bits/stl_algo.h:66:位于/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/random:38:在/ usr / bin包含的文件中/../lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/cmath:44:/ home / travis / build / myuser / perlin / include /math.h:48:28:错误:名称空间“ std”中没有名为“ is_arithmetic_v”的模板;您是说“ is_arithmetic”吗?

同样,它在gcc上构建良好。我还仔细检查了是否包括所有必需的标头。

我的.travis.yml看起来像这样:

language: cpp
dist: trusty

matrix:
  include:
  - os: linux
    addons:
      apt:
        sources:
        - ubuntu-toolchain-r-test …
Run Code Online (Sandbox Code Playgroud)

clang travis-ci c++17

5
推荐指数
1
解决办法
1494
查看次数