Создание нового примитивного типа

Есть ли способ создать новый тип, похожий на один из базовых типов (например, char), и может быть неявно преобразован между ними, но будет по-разному разрешаться в шаблонах, так что, например, работает следующий код?

typedef char utf8;
template<typename T>void f(T c);
template<> void f<char>(char c)
{
    std::cout << "ascii " << c << std::endl;
}
template<> void f<utf8>(utf8 c)//error C2766: explicit specialization; 'void f<char>(char)' has already been defined
{
    std::cout << "utf8 " << c << std::endl;
}
int main()
{
    char c1 = 'x';
    utf8 c2 = 'g';
    f(c1);
    f(c2);
}

Я думаю, что это может быть возможно с классом, содержащим один элемент данных, если да, то каков самый чистый способ сделать это, и смогут ли компиляторы оптимизировать его, как если бы он был примитивным.

РЕДАКТИРОВАТЬ: я попробовал BOOST_STRONG_TYPEDEF, и это, кажется, работает для основных вещей, но как я могу затем создать std::basic_string из нового типа?

BOOST_STRONG_TYPEDEF(char,utf8);
//first try
BOOST_STRONG_TYPEDEF(std::string,utf8_string);
//second try
typedef std::basic_string<utf8, std::char_traits<utf8>,std::allocator<utf8> > uft8_string;

Первый на самом деле не работает, потому что результирующий тип все еще ожидает char для всех своих методов, а второму, похоже, не нравится наличие конструкторов и операторов присваивания :(

Я еще не пробовал другой способ создать новый тип char, сможет ли он обойти это, если я не могу использовать BOOST_STRONG_TYPEDEF?


person Fire Lancer    schedule 15.10.2009    source источник
comment
Недостатком вашего плана является то, что, несмотря на свое название, UTF-8 не имеет ширины 8 бит. Это переменная ширина от 8 до 32 бит. Поэтому один символ может представлять только крошечное подмножество UTF-8 (фактически подмножество из 128 символов ASCII).   -  person Clifford    schedule 15.10.2009
comment
Вот почему мне нужны типы, которые могут использовать разные специализации и перегрузки шаблонов, чтобы он использовал версии метода, учитывающие тот факт, что UTF-8 (и UTF-16) может использовать несколько элементов для одного символа.   -  person Fire Lancer    schedule 15.10.2009


Ответы (3)


Я слышал слух, что C++0x принесет сильные определения типов, которые позволят классу utf8 в вашем случае отличиться от char, но в настоящее время этого не существует. Возможно, strong typedef от Boost поможет, но я не знать.

person Kylotan    schedule 15.10.2009

Автор C++ Мэтью Уилсон называет то, что вы описываете, «настоящими определениями типов». Они реализованы как класс, содержащий один элемент данных (как вы и сказали). Он описывает их и предоставляет реализацию шаблона в главе 18 Imperfect C++ (кстати, хорошая книга) и в эта статья в Dr. Журнал Добба.

Что касается оптимизации, любой хороший компилятор должен быть в состоянии оптимизировать это как примитив (поскольку, например, большие части STL полагаются на подобную качественную оптимизацию), но у меня нет никакой специфики.

person Josh Kelley    schedule 15.10.2009
comment
Истинный; Итераторы std::vector<T> — это тонкие оболочки для T*, и хороший оптимизатор должен иметь с этим дело. - person MSalters; 15.10.2009

Проблема здесь в том, что typedef на самом деле не определяет новые типы (например, Ada, где вы можете определять взаимно несовместимые целые типы), а только псевдонимы для существующих.

Я считаю, что одно из предложений для следующей версии C++ будет включать правильные типы.

person T.E.D.    schedule 15.10.2009