【问题标题】:Are Variadic Templates Sufficient to Specify Constructive Types可变参数模板是否足以指定构造类型
【发布时间】:2014-03-26 21:38:09
【问题描述】:

我的目标是定义一个模板来创建一个构造类型,例如:

MyCT := foo | bar of int | baz of WeirdClass | bat of (String, MyCT)

在内部,前缀将是枚举类型的字节值,因此: {0}{1,-20}{2,{weirdo:WeirdClass}}{3,{"Like I said",0}}{3,Pair<String,MyCT>{"a",{1,626}}} 等。

看起来可变参数模板的... 语法可能会有所帮助,但我担心以下几点:

  1. 可以根据枚举值的个数创建多个构造函数吗?
  2. 如果枚举值的个数不等于对应类型的个数,会不会抛出编译时错误?
  3. 模板创建的类型本身就是MyCT<ET> 形式的模板,其中ET 是枚举类型。我们如何确保我们可以只使用与枚举值对应的构造函数?
  4. 如果MyCT<et> 中的et 不在模板的枚举类型ET 中,我们能否抛出编译时错误?
  5. 我们可以这样做以使 MyCT<foo> 类型匹配 MyCT<baz>

【问题讨论】:

  • 问题不清楚。我没有看到 compile-time|runtime 障碍在哪里:为什么要进行枚举标记?该枚举值是在运行时指定的吗?如果所有东西都是在编译时提供的,我认为我们可以轻松地重新设计它并使用一些模板元编程让它工作。
  • 这个目标值得称道,但并不是真的可以实现。我真诚的建议是忘记它。如果您想要 ML 或 Haskell,您知道在哪里可以找到它们。
  • 感谢您的想法,Manu343726。以下不应该编译并且应该给出一个编译时错误:ConstrType 因为 ET 有四个值并且只提供了三个类型。这应该很容易通过检查语法来处理。假设我们有一个具有正确语法的构造类型模板,并将其实例化如下: template public class MyCT;模板 public class MyCT : ConsrType>>{ ... } (除了语法)我们希望在 MyCT 中严格键入 et 。没有 MyCT.

标签: c++ constructor variadic-templates


【解决方案1】:

为了让这更有趣,让我们在这个构造类型上定义一个(递归)函数fuz,使用类似 ML 的语法:

let rec fuz = fun (foo)      -> 4
                | (bar b)    -> 2 * b
                | (baz w)    -> w.eird
                | (bat(s,m)) -> length(s) - fuz(m);;

在哪里(比如说)

#type WeirdClass = {eird:int};;

所以我们开始使用 C++ (live example):

struct WeirdClass { int eird; };

struct MyCT { virtual int fuz() const = 0; };

struct foo : MyCT
{
    virtual int fuz() const override { return 4; };
};

struct bar : MyCT
{
    int b;
    bar(int b) : b(b) { }
    virtual int fuz() const override { return 2 * b; };
};

struct baz : MyCT
{
    WeirdClass w;
    baz(const WeirdClass& w) : w(w) { }
    virtual int fuz() const override { return w.eird; };
};

struct bat : MyCT
{
    std::string s;
    const MyCT& m;
    bat(const std::string& s, const MyCT& m) : s(s), m(m) { }
    virtual int fuz() const override { return s.length() - m.fuz(); };
};

int main()
{
    foo f;
    bar r{-20}, c{626};
    baz z{{8}};
    bat a{"Like I said",f};
    bat t{"no templates needed",c};

    cout << f.fuz() << " " <<  r.fuz() << " "
         << c.fuz() << " " <<  z.fuz() << " "
         << a.fuz() << " " <<  t.fuz() << endl;
}

输出:

4 -40 1252 8 7 -1251

不需要奇怪的可变参数模板。

【讨论】:

  • 是的,我希望完全实例化的模板具有这种 ML 功能,并为术语代数做了类似的事情。然而,在这个问题中,我更进一步,想知道现在是否可以用 C++ 简洁地表示术语代数的幼稚实现。显然,目前还不是这种情况。
  • @CarlKlapper 作为一种运行时解决方案,多态类型可以是构造类型的直接转换,如我的示例所示。我认为您在问题中建议的混合方式几乎是不可能的。然而,纯编译时可能是一种选择,因为 C++ 模板非常强大。如果你有兴趣,去年我实现了一个微型编译时 Scheme/CAML 解释器,不幸的是它没有类型,但它甚至支持像 Scheme 的 set! 这样的命令式方面。当编译器运行 10 分钟时,我停止了,占用了 24GB 内存,至少产生了正确的结果:-)
猜你喜欢
  • 1970-01-01
  • 2018-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多