小编Pet*_*efi的帖子

在C++中扩展类型

遗憾的是,UFCS没有进入C++ 17,这给我带来了一个反复出现的问题:有时我想使用方法调用语法给类型提供额外的功能(不需要编写全局函数).在处理monad时,这尤其方便.

我看到两个选项:一个是继承,另一个是封装.因为您无法安全地从STL容器继承,所以会留下封装.例如,我想扩展std::optional,所以我写道:

template <typename T>
struct myoption {
    // Some functionality
private:
    std::optional<T> impl;
};
Run Code Online (Sandbox Code Playgroud)

我的问题是,每次我想要这样做时,我基本上都必须编写push_back原始类型具有的所有构造函数(以及可以与原始类型一起使用的所需方法,如向量).即使是更简单的容器,也可选有9个构造函数.使用继承时,我可以简单地"继承"超类的方法和构造函数.有没有办法使用封装更容易?

c++ extension-methods encapsulation

11
推荐指数
1
解决办法
325
查看次数

惰性评估依赖类型(CRTP)

我希望以下代码能够工作:

template <typename Self>
struct foo_base {
    auto get(typename Self::type n) { return n; }
};

template <typename T>
struct foo : public foo_base<foo<T>> {
    using type = T;
};
Run Code Online (Sandbox Code Playgroud)

问题当然是首先实例化基础,因此您不能引用派生成员类型.我需要在这里进行某种懒惰的评估.

我已经尝试制作功能模板并在其上安装了SFINAE,类似于:

template <typename Self>
struct foo_base {
    template <typename T, typename = std::enable_if_t<std::is_same_v<T, typename Self::type>>>
    auto get(T n) { return n; }
};
Run Code Online (Sandbox Code Playgroud)

但它似乎不会影响订单.有任何想法吗?

编辑:

解决方案的限制:

  • 我无法从派生类传递类型作为模板参数.主要原因是:构造类型很复杂,有几百个字符.所以不能做类似的事情struct foo : foo_base<foo<T>, T>或变种.
  • 我需要将函数约束到该类型,我无法检查函数内部.也许派生类中存在重载.

c++ crtp c++17

7
推荐指数
1
解决办法
291
查看次数

类型的C++ constexpr值

我希望能够在类型的ID上创建switch语句.我找到了一种机制,可以为不同类型提供唯一的ID.这很简单:

template <typename T>
struct type { 
    static void id() { } 
};

template <typename T>
constexpr const size_t type_id() {
    return reinterpret_cast<size_t>(&type<T>::id); 
}
Run Code Online (Sandbox Code Playgroud)

我认为这将评估为一个常量,我可以用作开关的情况.但是当我执行以下操作时,我得到一个错误,即case表达式不是常量:

int main(void) {
    size_t a = type_id<int>();
    switch (a) {
    case type_id<int>():
        break;
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

为什么不是常数?我怎么能达到这个效果?

编辑:

如果没有reinterpret_cast,我可以做这样的事情吗?

c++ templates unique constexpr c++11

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

使用二进制前缀,中缀和后缀运算符解析表达式

是否有可能解析一个表达式(没有歧义),它可以包含二进制前缀,二进制中缀和二进制后缀运算符(让我们假设所有符号都不同),它们之间具有优先权?例如:

a = 2 3 post+
b = pre+ 2 3*4
Run Code Online (Sandbox Code Playgroud)

然后a将等于5因为=优先级低于后缀post+运算符并且b将是14.我知道你可以用运算符优先解析或分流码解析中缀表示法,但这个问题对我来说似乎要复杂得多.

编辑:

允许括号,并且运算符的前/后变体具有与中缀相同的优先级.

我想推出一个手写算法.

EDIT2:

按优先顺序,我指的是消费多少.例如:

a = 2 3 post+
Run Code Online (Sandbox Code Playgroud)

可能导致这些AST-s:

'=' has higher precedence than 'post+':
    post+
    /  \
   =    3
  / \
 a  2

'post+' has higher precedence than '=':
      =
     / \
   a   post+
       /  \
      2    3
Run Code Online (Sandbox Code Playgroud)

(第二个是我在这种情况下需要的).我不能真正使用现有的解析器生成器或固定语法来操作数,因为运算符是动态加载的.

parsing operator-precedence infix-operator prefix-operator postfix-operator

5
推荐指数
0
解决办法
465
查看次数

C++ 中的模式匹配

我正在用 C++ 编写一个编译器,与任何编译器一样,它需要大量的模式匹配和动态转换。在 Rust、Haskell 和 OCaml 等语言中,我可以轻松地破坏类型,例如:

match node {
    Binary{ left, right, operator } => { .. }
    _ => { .. }
}
Run Code Online (Sandbox Code Playgroud)

在 C++ 中我能做的最好的事情是:

if (auto bin = dynamic_cast<Binary*>(node)) { ... }
else if (...) { ... }
Run Code Online (Sandbox Code Playgroud)

如果您将智能指针引入场景中,这确实是有限且丑陋的。例如,如果我需要匹配 2 个东西:

bool matched = false;
if (auto m1 = dynamic_cast<Foo*>(a)) {
    if (auto m2 = dynamic_cast<Bar*>(b)) {
        matched = true;
    }
}
if (!matched) {
    // This is because C++ does not allow you to declare …
Run Code Online (Sandbox Code Playgroud)

c++ pattern-matching

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

在C++中减少模板化的类参数

我有一个这样的课:

template <unsigned int A, unsigned int B>
class Foo { ... };
Run Code Online (Sandbox Code Playgroud)

Foo需要一个名为bar()的方法,但我需要专门化它.对于一个案例,当A == B时,我希望它做一件事,否则就是其他事情.如果不在函数中编写if语句,我可以这样做吗?喜欢:

Foo<A, A>::bar() { ... } and Foo<A, B>::bar() { ... }
Run Code Online (Sandbox Code Playgroud)

c++ templates

4
推荐指数
1
解决办法
79
查看次数

Rust如何在数组中存储枚举值?

以下是有效的Rust:

enum Foo {
    One(i32, i32, i32),
    Two { x: i32, y: i32 },
}

fn main() {
    let x: [Foo; 2] = [Foo::One(1, 2, 3), Foo::Two { x: 1, y: 2 }];
}
Run Code Online (Sandbox Code Playgroud)

Rust如何存储这个?第一个元素是12个字节,而第二个元素是8(我想在开头加上一个标记字节).它是否只存储对数组中元素的引用?

memory enums rust

4
推荐指数
2
解决办法
678
查看次数

Rust如何解决Hindley-Milner的可变性?

我读过Rust在使用Hindley-Milner时具有很好的类型推断。Rust还具有可变变量,并且当HM算法具有可变性时,AFAIK必须存在一些约束,因为它可能过于笼统。如下代码:

let mut a;
a = 3;
a = 2.5;
Run Code Online (Sandbox Code Playgroud)

不进行编译,因为在第二行推断出整数,并且不能将浮点值分配给整数变量。因此,我猜测对于简单变量,一旦推断出非泛型类型,该变量就会成为单类型并且无法再进行泛化。

但是,像Vec这样的模板呢?例如此代码:

let mut v;
v = Vec::new();
v.push(3);
v.push(2.3);
Run Code Online (Sandbox Code Playgroud)

这再次失败,但对于最后一行再次失败。这意味着第二行部分推断了类型(Vec),而第三行推断了容器类型。

怎么了 有我不知道的诸如价值限制之类的东西吗?还是我使事情复杂化了,Rust有更严格的规则(就像根本没有泛化一样)?

mutable hindley-milner rust

4
推荐指数
2
解决办法
945
查看次数