有没有办法模拟“strongdef”?

时间:2012-09-20 19:33:52

标签: c++ typedef

您可能知道typedef更像是C ++中的别名而不是新类型,详情可以在这里看到: http://dlang.org/cpptod.html#typedefs
我真的不喜欢链接中提出的解决方案,所以我想知道有更好的方法吗?

5 个答案:

答案 0 :(得分:7)

只有一种方法可以在C ++中引入新类型 - 带有类关键字(union / struct / class / enum ...)。有一些方法可以隐藏宏后面的这些东西,并使这些新类型与旧版本一样直观可用(参见BOOST_STRONG_TYPEDEF),但事实仍然是它是引入这种新类型的唯一方法。 / p>

想象一下,你有一个newtype关键字,它构成了一个强大的typedef:

newtype foo = int; // with 'using' alias syntax

该类型的转化如何运作?如果没有转换,您永远不能为新类型的对象分配任何值。只有显式转换可能看起来很直观,但是如果真的想要隐式转换,并且仍能够重载怎么办?好吧,运气不好。您可以添加各种语法以将决定留给用户,但我确信您始终可以提出需要新语法的极端情况。只需将其设为struct,将其隐藏在宏后面即可完成。

答案 1 :(得分:2)

通用“没时间制作正确的界面”宏:

#define STRONG_CLASS_TYPEDEF(oldType, newType) \
struct newType : private oldType {             \
    template<typename... T>                    \
    newType(T... foo) : oldType(foo...) {}     \
    oldType* operator->() { return this; }     \
    oldType& operator*() {return *this;}       \
};

如果编译器不支持可变参数模板,则需要手动插入所需的构造函数。这基本上是一个构建你自己的继承构造函数。

不幸的是,我认为不可能将新类型限制为隐式转换为基类,而是公开其所有公共字段。有一些解决方法:

您只需using oldType::X;所需的所有方法和变量即可。这绝对是最好的解决方案,但需要一段时间才能完成。

或者使用偷偷摸摸的箭头操作符重载并调用foo->method();。或者“取消引用”新的强类型到基类型。这些基本上只是一个花哨的显式演员。但是考虑operator oldType()(显式与否)甚至不能用于私有继承......

无论如何,这是std::stringName示例的强类型。

struct Name : private std::string {
    template<typename... T>
    Name(T... foo) : std::string(foo...) {}

    std::string* operator->() { return this; }
    const std::string& operator*() {return *this;}
    //The above is obviously a bad idea if you want to use this alongside pointers

    using std::string::resize;
    using std::string::size;
    using std::string::insert;
    using std::string::operator[];
    // etc.
    //Simplest to use, but a bit more to set up
};

此外,您必须在此示例中包装非成员运算符重载(std :: string ==)。

bool operator==(Name& lhs, Name& rhs) { return *lhs == *rhs; }
//Note: "Dereference" turns it into a std::string, as above

公平警告,除了基本机制之外,我没有进行太多测试。它可能会增加(非常)少量的开销。但是有效的空类是可能已经优化了。

答案 2 :(得分:1)

使用BOOST_STRONG_TYPEDEF在C ++中创建“strongdefs”。没有内置语言功能。

那说知道你试图解决的真正问题会很有趣,因为我发现非别名typedef在我所使用的代码中非常小。< / p>

答案 3 :(得分:0)

C ++中的新类型只能以某种方式聚合子类型。但由于函数重载基于静态类型,因此必须重新声明所有操作和函数。

C ++ typedef就像D alias es。

如果起始类型是一个类或结构,继承可以以某种方式帮助(至少操作仍然可以像旧参数一样工作)但是一切都是关于返回类型的,必须正确地重新定义转换,否则一切都会无差别地上下转换从而消除了新型的优势。

答案 4 :(得分:0)

C ++中有很多方法可以执行类型检查。 考虑以下代码,基本思想与链接中给出的示例相同,但我认为它更直接:

struct Handle2 {void * ptr;} ;
void bar(Handle2) {}
void foo(void *) {}

int main() {
    Handle2 h2 = {(void*)-1};
    foo(h2); //! won't pass through compiling
    bar(h2);
}