C++ 中严格 typedef 的成语

Posted

技术标签:

【中文标题】C++ 中严格 typedef 的成语【英文标题】:Idiom for strict typedef in C++ 【发布时间】:2013-02-06 23:40:34 【问题描述】:

C++ 中是否存在严格 typedef 的习惯用法,可能使用模板?

类似:

template <class base_type, int N> struct new_type
    base_type p;
    explicit new_type(base_type i = base_type()) : p(i) 
;

typedef new_type<int, __LINE__> x_coordinate;
typedef new_type<int, __LINE__> y_coordinate;

所以我可以使这样的事情成为编译时错误:

x_coordinate x(5);
y_coordinate y(6);

x = y; // whoops

那里的__LINE__ 看起来可能很麻烦,但我不希望仅仅为了保持每种类型的唯一性而手动创建一组常量。

【问题讨论】:

坐标不是一个很好的应用程序。两个坐标的乘积不是坐标等。您可能需要查看 Boost.Units。 我删除了建议 BOOST_STRONG_TYPEDEF 的答案,因为显然这适用于重载解决方案,但不会在交叉分配时产生编译错误。 我质疑你想做的事情的价值。例如,当您想要执行旋转时会发生什么? x = sin(theta)*y + cos(theta)*x 应该是完全有效的。 这对于 base_type == int 来说是最需要的,但是如果提供了到/从 int 的转换,那么整个目的就失去了。解决方案是只提供“to”或“from”转换,并使用 fn 【参考方案1】:

没有。有人提议将其纳入下一个标准(C++14,或者可能是 C++17),但不在 C++11 中。

【讨论】:

-1:他没有问是否在语言中,在“用户空间”中有种方法可以做到这一点。因此,这个答案是错误的。 在用户空间中没有与提议的语言功能相同的方法。 那与问题中所说的相同吗?既然 Angew 的回答已经无效,我愿意接受这种可能性,但需要您在此处输入。 因为 new_type 在许多情况下实际上并不像它的原始类型。比如你不能new_type&lt;std::string, ...&gt;().c_str(); @Puppy 这个问题没有具体提到 C++11,但我看到你的答案是 2013 年写的。你会考虑更新它吗? (有什么东西进去了吗?)【参考方案2】:

我在我的项目中使用了类似的东西。只有我使用类型标记而不是 int。在我的特定应用中运行良好。

template <class base_type, class tag> class new_type     
  public:   
    explicit new_type(base_type i = base_type()) : p(i) 

    //
    // All sorts of constructors and overloaded operators
    // to make it behave like built-in type
    //

  private:
     base_type p;
;

typedef new_type<int, class TAG_x_coordinate> x_coordinate;
typedef new_type<int, class TAG_y_coordinate> y_coordinate;

请注意,TAG_* 类不需要在任何地方定义,它们只是标签

x_coordinate x (1);
y_coordinate y (2);

x = y; // error

【讨论】:

我认为使用简单的“#define new_type(base, tag) typedef new_type tag;”会更好看 @slacy 不知道,我觉得宏很难看并避免使用它们 宏不只是丑陋的;由于不遵守范围,它们也会引起问题。他们是我最后的手段。 (如果您想将它用于类似的事情,请考虑在之后使用#undef。但是,如果其他人定义了该宏,这可能会导致其他问题,因为您将取消定义他们的宏。因此,您需要检查以确保没有人否则用相同的名称定义一个宏。等等)【参考方案3】:

使用 C++11:

#include <stdio.h>

struct dummy ;

struct NotMineType

    NotMineType(dummy) 
;

template <int N>
struct type_scope

    struct MyOwnType
    
    ;

    struct ConvertedToMineType : NotMineType
    
        template <typename ...Args>
        ConvertedToMineType(Args... args) : NotMineType(args...) ;
    ;

    enum myint : int ;
;

typedef type_scope<0>::MyOwnType x1;
typedef type_scope<1>::MyOwnType x2;

typedef type_scope<0>::ConvertedToMineType y1;
typedef type_scope<1>::ConvertedToMineType y2;

typedef type_scope<0>::myint i1;
typedef type_scope<1>::myint i2;

void foo(x1)  printf("x1\n"); 
void foo(x2)  printf("x2\n"); 
void foo(y1)  printf("y1\n"); 
void foo(y2)  printf("y2\n"); 
void foo(i1)  printf("i1\n"); 
void foo(i2)  printf("i2\n"); 

int main()

    foo(x1());
    foo(x2());
    foo(y1(dummy()));
    foo(y2(dummy()));
    foo(i1());
    foo(i2());

输出:

x1
x2
y1
y2
i1
i2

编译器:

Visual Studio 2015,GCC 4.8.x

【讨论】:

以上是关于C++ 中严格 typedef 的成语的主要内容,如果未能解决你的问题,请参考以下文章

Apollo GraphQL - 将 .graphql 模式导入为 typeDefs

C++中用于对象构造的**成语

React Native Build Error on IOS - typedef用不同类型重新定义('uint8_t'(又名'unsigned char')与'enum clockid_t')

我啥时候应该在 C++ 中使用 typedef?

尾随数组成语

C++ 中 typedef 的前向声明