Специализация шаблона С++ - недопустимый тип для параметра шаблона, не являющегося типом '__formal

Мне нужно проанализировать кадры пользовательского протокола, которые могут содержать целые числа различных размеров (uint8_t, uint16_t, uint32_t и т. д.) и строки символов с префиксом их длины (uint16_t).

Я хочу написать шаблонную функцию для чтения таких значений из вектора байтов, чтобы сделать синтаксис более читабельным. Вот мои функции:

template< typename type >
type read( const std::vector< byte > & bytes, uint index )
{
    if( index + sizeof( type ) > bytes.size() )
    {
        throw exception( "read() - Out of range." );
    }

    type val;
    memcpy( & val, & bytes[ index ], sizeof( type ) );

    return val;
}

template< std::string >
std::string read( const std::vector< byte > & bytes, uint index ) // ERROR HERE
{
    if( index + sizeof( type ) > bytes.size() )
    {
        throw exception( "read() - Out of range." );
    }

    uint16_t length = read< uint16_t >( bytes, 0 );

    std::string str( length, '\0' );

    for( uint16_t i = 0; i < length; ++i )
    {
        str[i] = read< char >( bytes, index + i );
    }

    return str;
}

Я получаю эту ошибку на VS2005:

Error   1   error C2993: 'std::string' : illegal type for non-type template parameter '__formal'    c:\dev\floatinglicences\common\common.h 50

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

Ты мне поможешь ? Спасибо :)


person Virus721    schedule 06.06.2014    source источник
comment
Разве человек невежлив, когда намеренно не делает того, что должен, или когда это просто не приходит ему в голову?   -  person Virus721    schedule 06.06.2014
comment
Я бы сказал так. Это отсутствие размышлений о вашей аудитории и размышление только о собственной проблеме. Хотя, может быть, это скорее невнимательно, чем невежливо, выбирайте сами. В любом случае, урок усвоен, и спасибо за быстрый ответ.   -  person Kerrek SB    schedule 06.06.2014
comment
Ладно, в любом случае спасибо за помощь всем. Я выберу самый быстрый ответ, так как они все одинаковы :)   -  person Virus721    schedule 06.06.2014
comment
Не стесняйтесь принимать ответ от кого-то, кто новее или имеет меньшую репутацию. Я не думаю, что кому-то из высокопоставленных людей нужно больше, и это вдохновляет молодых быть принятыми.   -  person Kerrek SB    schedule 06.06.2014
comment
@KerrekSB Ага. У меня еще вопрос, если можно. Что, если бы я захотел специализировать свою функцию для обработки basic_string‹T› вместо string ? :)   -  person Virus721    schedule 06.06.2014
comment
@ Virus721: Вы не можете частично специализировать шаблоны функций. Поищите на этом сайте, там много связанных вопросов и возможных решений.   -  person Kerrek SB    schedule 06.06.2014


Ответы (4)


Изменено с:

template< std::string >
std::string read( const std::vector< byte > & bytes, uint index ) 

к этому:

template<>
std::string read< std::string >( const std::vector< byte > & bytes, uint index ) 
person bstar55    schedule 06.06.2014

Специализация выглядит так:

template <typename T>
void foo(A x, B y, C z);                    // primary template

template <>
void foo<std::string> foo(A x, B y, C z);   // specialized for T = std::string
person Kerrek SB    schedule 06.06.2014

Специализация должна быть:

template<>
std::string read< std::string >( blah blah blah)
person Jonathan Wakely    schedule 06.06.2014

Явная специализация выглядит так:

template <>
std::string read<std::string>( const std::vector< byte > & bytes, uint index )
{
    // ...
}

Здесь первый <> — это набор параметров шаблона. Их нет, поскольку вы указываете точный тип функции, а не другой шаблон. Второй <> — это аргументы шаблона, определяющие определяемую специализацию шаблона.

Обратите внимание, что определение явной специализации принадлежит исходному файлу, а не файлу заголовка. Если вы не добавите inline.

person aschepler    schedule 06.06.2014
comment
Спасибо за примечание о inline! - person sgryzko; 05.03.2015