2012-03-06 52 views
14

Tôi muốn sử dụng một cái gì đó như typedef trong các chương trình C++ của tôi để tăng cường an toàn loại.typesafe typedef trong C++

Như một ví dụ, giả sử tôi có hai chức năng

void function1(unsigned idOfType1); 
void function2(unsigned idOfType2); 

sau đó tôi nhầm lẫn có thể vượt qua idOfType2 để Function1 và ngược lại. Tôi muốn trình biên dịch cho tôi một lỗi trong trường hợp này. Tôi biết rằng tôi có thể bọc các unsigned trong một cấu trúc, nhưng sau đó tôi phải cung cấp cho cung cấp một tên trường và sử dụng . để truy cập chúng, đó là hơi bất tiện. Có cách nào tốt cho việc này không?

Chỉnh sửa: Theo như tôi biết typedef sẽ không hoạt động cho mục đích này vì nó chỉ là viết tắt của một loại và sẽ không được sử dụng để kiểm tra loại.

+2

Enums làm việc tốt trong trường hợp của bạn ... –

+0

@AlexanderPavlov cẩn thận để xây dựng, nó không phải là hiển nhiên đối với tôi ... – Paul

+2

@Paul: bạn có thể viết một cái gì đó như 'enum Type1 {dummy0 = 1, dummy1 = 1 << 1, dummy2 = 1 < <2, ..., dummy31 = 1 << 31}; ', và giả sử' unsigned' là một loại 32 bit trên thực hiện của bạn thì kết quả là một enum có thể giữ bất kỳ giá trị nào của 'unsigned'. Sau đó, 'void function1 (Type1 id)' sẽ không chấp nhận một 'Type2', bởi vì enums không chuyển đổi hoàn toàn với nhau. –

Trả lời

6

Như bạn nói, typedef sẽ không giúp bạn ở đây. Tôi không thể nghĩ ra một cách tốt hơn ngay lập tức, tuy nhiên nếu bạn đi với gói của bạn trong một tùy chọn struct/class bạn có thể sử dụng toán tử chuyển đổi để loại bỏ phương thức thành viên hoặc hàm call.

Ví dụ:

struct WrappedType 
{ 
    operator type() 
    { 
     return _value; 
    } 

    type _value; 
} 

Tôi không nói rằng đây là các cách để làm điều đó phiền bạn ;-)

+1

bạn có thể chỉ cho tôi cách tôi có thể sử dụng toán tử kiểu này không? có thể không hoạt động trong trường hợp của tôi, vì vậy tôi quan tâm đến giải pháp này! – Paul

+0

Theo như tôi hiểu, đó chính xác là những gì typedef mạnh mẽ của boost làm ... – Griwes

+1

@Konrad tuyệt vời Cảm ơn bạn đã xây dựng.Nếu tôi không thể sử dụng tăng mạnh typedef sau đó tôi sẽ sử dụng giải pháp này – Paul

15

Sử dụng Boost strong typedef:

typedef tạo ra một bí danh cho một loại hiện có. Nó không tạo ra một loại mới có thể được sử dụng cho phù hợp với một trong hai chức năng hoặc các thông số mẫu ...

Sử dụng BOOST_STRONG_TYPEDEF địa chỉ này ...

BOOST_STRONG_TYPEDEF là một vĩ mô mà tạo ra một lớp có tên là "tên" kết thúc tốt đẹp và thể hiện kiểu nguyên thủy của nó và cung cấp các toán tử chuyển đổi thích hợp để làm cho kiểu mới có thể thay thế được cho kiểu mới mà nó kết thúc tốt đẹp.

+1

Tôi nên có kiểm tra tăng trước khi yêu cầu ... cảm ơn cho câu trả lời nhanh chóng! – Paul

+0

Lưu ý rằng Boost typedef mạnh mẽ cho phép chuyển đổi ngầm định trong các bài tập – larsch

0

Có một C++ 11 tính năng gọi là enum class, đó là về cơ bản là một loại enum an toàn. Có lẽ họ có thể giúp đỡ ở đây.

+1

'enum' s luôn luôn an toàn, ví dụ: 'enum x {a}; enum y {b}; y = a; 'sẽ không biên dịch.- –

+1

@phresnel Tôi nghĩ rằng điều này chỉ đúng một nửa vì enums sẽ được chuyển đổi hoàn toàn thành ints, phải không? – Paul

+0

@Paul: chúng ta hãy đồng ý với 0,75 * đúng, ngược lại là không đúng sự thật. Vì vậy, có vẻ như enums là 75% typesafe, ... –

-2

Bạn có thể kiểm tra loại trong chức năng của mình, để nếu nó không khớp, bạn có thể in lỗi hoặc gì đó.

Bạn có thể sử dụng typeid phát hiện loại biến, như sau:

typeid(*variablename*).name() 

Như đã đề cập trong một trong các câu trả lời here, đây là biên dịch phụ thuộc và bạn phải sử dụng phương pháp thử-và-sai để tìm ra giá trị nào phù hợp với bạn.

+1

Nhưng sau đó tôi sẽ phải làm điều đó trong __every__ gọi hàm + nó phụ thuộc vào trình biên dịch? xin lỗi, tôi không nghĩ rằng đây là một lựa chọn tốt ... – Paul

+0

Không hoạt động - kiểu tham số 'idOfType1' trong' function1' luôn là 'unsigned'. Những gì đã được thông qua bởi người gọi đã được chuyển đổi. –

2

Tôi muốn điều này thành ngôn ngữ. Không phải là một câu trả lời cho mỗi gia nhập, nhưng ... :)

Opaque typedefs

1

Đây là một bài trả lời muộn để một câu hỏi cũ.Nhưng cũng có những bước phát triển mới trên C++ trước và vì lợi ích của sự hoàn chỉnh tôi thêm câu trả lời này:

Các opaque_typedef thư viện là nỗ lực của tác giả để cung cấp hầu hết các giá trị của typedefs đục thông qua thư viện, mà không phải chờ đợi typedefs đục để trở thành một tính năng ngôn ngữ.

Tác giả của thư viện này, Kyle Markley đã giới thiệu short brilliant speech at the cppcon 2015 giới thiệu thư viện này. Các trang trình bày của bài phát biểu của anh ấy có trên github mã nguồn của thư viện có sẵn trên sourceforge. Thư viện là chỉ tiêu đề, được viết bằng C++ 11. Gcc và clang là ok, nhưng VS2015 dường như có vấn đề với nó.

Việc sử dụng thư viện là thẳng về phía trước. Đoạn mã sau được lấy từ tài liệu. Nó tạo ra một typedef đục của int. Nó có giao diện giống như một int (nó có thể được thêm vào, dịch chuyển, tăng dần, so sánh, vv) nhưng các đối số và giá trị trả về là của kiểu mới được tạo ra, không phải của int:

#include "opaque/numeric_typedef.hpp" 

struct myint : opaque::numeric_typedef<int, myint> { 
    using base = opaque::numeric_typedef<int, myint>; 
    using base::base; 
};