13

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

4

5 回答 5

7

只有一种方法可以在 C++ 中引入新类型 - 使用类关键字 ( /// ... union) 。有一些方法可以将这些东西隐藏在宏后面,并使这些新类型与旧类型一样直观可用(请参阅 参考资料),但事实仍然是它是引入这种新类型的唯一方法。structclassenumBOOST_STRONG_TYPEDEF

想象一下,你有一个newtype关键字可以创建一个强 typedef:

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

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

于 2012-09-20T19:42:14.440 回答
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::stringandName例子。

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

公平的警告,除了基本的力学之外,我没有测试太多。它可能会增加(非常)少量的开销。但是实际上空的类可能被优化掉了。

于 2013-04-26T08:19:31.677 回答
1

用于BOOST_STRONG_TYPEDEF在 C++ 中创建“strongdefs”。没有内置的语言功能可以这样做。

也就是说,了解您要解决的真正问题会很有趣,因为我发现在typedef我处理的代码中对非别名的需求非常少。

于 2012-09-20T21:02:49.883 回答
0

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

C++typedef就像 D 一样alias

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

于 2012-09-20T19:44:30.283 回答
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);
}
于 2013-04-30T21:47:08.320 回答