2015-09-29 2 views
11

В C++ 11 есть ли чистый способ отключить неявное преобразование между typedefs, или вам нужно сделать что-то неприятное, как обернуть int в класс и определить и удалить различные операторы?Отключить неявное преобразование между typedefs

typedef int Foo; 
typedef int Bar; 
Foo foo(1); 
Bar bar(2); 
bar = foo; // Implicit conversion! 
+3

определения типов не являются реальными типами, они просто Shorthands или псевдонимы для реальных типов. – Barmar

+0

Так что 'foo' и' bar' на самом деле одного типа, и никакого преобразования не требуется. – Barmar

+0

Да, это понятно. Но имеет ли современный C++ замену, которая создает новый тип без кучи шаблона? –

ответ

5

стандарта C++ говорит:

7.1.3 ЬурейеЕ спецификатор

Имя объявляется с ЬурейиМ спецификатором становится именем ЬурейиМ. В пределах своей декларации имя typedef равно , синтаксически эквивалентное ключевому слову, и называет тип, связанный с идентификатором, в способом, описанным в разделе 8. Typedef-name , таким образом, является синонимом другого типа. A-имя ЬурейеЕ делает не вводит нового типа, как класс декларации (9.1) или декларации перечислимую делает

Но, например, class или struct ввести новые типы. В следующем примере uniqueUnused фактически ничего не используется, но используется для создания другого типа Value<int, 1> != Value<int, 2>. Так что, возможно, это то, что вы ищете. Имейте в виду, что нет гарантии, что компилятор избавится от внешней структуры! Единственная гарантия этот код дает вам это тот же размер, как ИНТ

template<typename T, int uniqueUnused> 
struct Value 
{ 
    Value() : _val({}) {} 
    Value(T val) : _val(val) { } 
    T _val; 
    operator T&() { return _val; } 

    // evaluate if you with or without refs for assignments 
    operator T() { return _val; } 
}; 

using Foo = Value<int, 1>; 
using Bar = Value<int, 2>; 
static_assert(sizeof(Foo) == sizeof(int), "int must be of same size"); 
static_assert(sizeof(Bar) == sizeof(int), "int must be of same size"); 

Если вы хотите создать новый тип, основанный на классе вы можете просто пойти с этим примером (это не работает со скалярными типами, начиная с вы не можете наследовать от Интс):

class Foo : public Bar // introduces a new type called Foo 
{ 
    using Bar::Bar; 
}; 
5

HelloWorld объясняет, почему то, что вы не можете работать. Вам понадобится то, что обычно называют «сильным» typedef, чтобы делать то, что вы хотите. Пример реализации является BOOST_STRONG_TYPEDEF:

#include <boost/serialization/strong_typedef.hpp>  

BOOST_STRONG_TYPEDEF(int, a) 
void f(int x); // (1) function to handle simple integers 
void f(a x); // (2) special function to handle integers of type a 
int main(){ 
    int x = 1; 
    a y; 
    y = x;  // other operations permitted as a is converted as necessary 
    f(x);  // chooses (1) 
    f(y);  // chooses (2) 
} 

Если бы мы сделали typedef int a;, то код будет неоднозначным.

+0

Также хороший. Внедряет ли 'BOOST_STRONG_TYPEDEF' оболочку или это бесплатно? – HelloWorld

+0

@HelloWorld «BOOST_STRONG_TYPEDEF» - это макрос, который генерирует класс с именем «имя», который обертывает экземпляр его примитивного типа и предоставляет соответствующие операторы преобразования, чтобы сделать новый тип заменяемым для того, который он обертывает ». – Barry

+0

@HelloWorld Также он ** предложил ** ввести обертку по причинам, которые вы даете в своем ответе :) – Barry

-1

Это не строгая проверка типов, но незаконные преобразования могут из видимых с помощью оригинала или приложения Венгерской нотация (H. N.). Если вы считаете, что H. N. означает имя-тип-префикс, вы ошибаетесь (это System H. N., и это, hm, ненужные накладные наименования).

Использование (Приложения) H. N., префиксы переменных не являются типом (например, int), но цель, например. счетчик, длина, секунды и т. д. Итак, когда вы добавляете счетчик в переменную, истекшее время, вы пишете cntSomethingCounter + secElapsedSinceLastSomething, и вы можете видеть, что он пахнет. Компилятор не оповещает об этом, но он ткнул ваши глаза.

Подробнее: http://www.joelonsoftware.com/articles/Wrong.html

Смежные вопросы