c ++ странная специализация шаблона на внутренней переменной - PullRequest
0 голосов
/ 03 февраля 2012

Рассмотрим следующий код:

#include    <iostream>
#include    <typeinfo>
#include    <cstring>
#include    <cstdlib>

static void random_string( char *s, const int len )
{
    static const char alphanum[] =
        "0123456789"
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        "abcdefghijklmnopqrstuvwxyz";

    for ( int i = 0; i < len; ++i )
        s[ i ] = alphanum[ rand( ) % ( sizeof( alphanum ) - 1 ) ];

    s[ len ] = 0;
}

template< typename Type, int Length >
void    info( Type ( &var )[ Length ] )
{
    std::cout << "->    Type is " << typeid( var ).name( ) << std::endl;
    std::cout << "->    Pointer size:   " << sizeof( Type * ) << std::endl;
    std::cout << "->    Number of elements: " << Length << std::endl;
    std::cout << "->    Size of each element:   " << sizeof( Type ) << std::endl;
    std::cout << "->    contents: \"" << var << "\"." << std::endl;
}


template< typename SourceType, int SourceLength, typename TargetType, int TargetLength >
void    func( TargetType ( &target )[ TargetLength ] )
{
    SourceType  source[ SourceLength ];

    random_string( ( char * )source, SourceLength - 1 );

    std::cout << "-= source =-" << std::endl;
    info( source );

    std::cout << "-= target =-" << std::endl;
    info( target );

    std::memcpy( target, source,
            ( SourceLength < TargetLength ? SourceLength : TargetLength ) );
}

int main( )
{
    typedef char    char16[ 16 ];
    typedef char    char64[ 64 ];

    char16  c16 = "16 bytes chars.";
    char64  c64 = "64 bytes chars. There's a lot more room here...";

    std::cout << "c16 = \"" << c16 << "\"." << std::endl;
    func< char64, sizeof( char64 ) >( c16 );
    std::cout << "c16 = \"" << c16 << "\"." << std::endl;

    std::cout << "c64 = \"" << c64 << "\"." << std::endl;
    func< char16, sizeof( char16 ) >( c64 );
    std::cout << "c64 = \"" << c64 << "\"." << std::endl;

    return  0;
}

И этот вывод:

> g++ -Wall -g3 array_conversions.cpp -o array_conversions
> ./array_inner_type
c16 = "16 bytes chars.".
-= source =-
->      Type is A64_A64_c
->      Pointer size:   8
->      Number of elements:     64
->      Size of each element:   64
->      contents: "0x7fff8b913380".
-= target =-
->      Type is A16_c
->      Pointer size:   8
->      Number of elements:     16
->      Size of each element:   1
->      contents: "16 bytes chars.".
c16 = "fa37JncCHryDsbza".
c64 = "64 bytes chars. There's a lot more room here...".
-= source =-
->      Type is A16_A16_c
->      Pointer size:   8
->      Number of elements:     16
->      Size of each element:   16
->      contents: "0x7fff8b914280".
-= target =-
->      Type is A64_c
->      Pointer size:   8
->      Number of elements:     64
->      Size of each element:   1
->      contents: "64 bytes chars. There's a lot more room here...".
c64 = "Z2nOXpPIhMFSv8k".

Как мы видим, понимание того, что SourceType source[ SourceLength ] для меня и GCC, не одно и то же.

Я ожидал, что SourceType source[ SourceLength ] будет иметь тип char64 ("A64_c"), но GCC сообщает мне, что это "A64_A64_c" и действует так, как если бы это был массив char64 или что-то в этом роде. как.

Странно, это происходит только с локальной переменной source. Функциональный параметр target интерпретирован правильно.

Чего мне не хватает? Есть ли недоразумение в моем коде?

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

Действительно, спасибо.

Ответы [ 2 ]

1 голос
/ 03 февраля 2012

c16 имеет тип char[16]

func< char64, sizeof( char64 ) >( c16 ) создает func с

SourceType == char64 == char[64]
SourceLength == sizeof( char64 ) == 64
TargetType == char
TargetLength == 16

Это означает, что target имеет тип char (&)[16], а source имеет тип char[64][64].

Это объясняет, почему target является массивом char, а source является массивом char

0 голосов
/ 03 февраля 2012

Извините, извините ..

Это была действительно моя вина. Решение, на самом деле, действительно проще, чем то, что я пытался сделать. Я только что видел это благодаря словам друга.

К сожалению, он не вошел в систему, поэтому я просто вставлю рабочую версию того же кода:

#include    <iostream>
#include    <typeinfo>
#include    <cstring>
#include    <cstdlib>


static void random_string( char *s, const int len )
{
    static const char alphanum[] =
        "0123456789"
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        "abcdefghijklmnopqrstuvwxyz";

    for ( int i = 0; i < len; ++i )
        s[ i ] = alphanum[ rand( ) % ( sizeof( alphanum ) - 1 ) ];

    s[ len ] = 0;
}

template< typename Type, int Length >
void    info( Type ( &var )[ Length ] )
{
    std::cout << "->    Type is " << typeid( var ).name( ) << std::endl;
    std::cout << "->    Pointer size:   " << sizeof( Type * ) << std::endl;
    std::cout << "->    Number of elements: " << Length << std::endl;
    std::cout << "->    Size of each element:   " << sizeof( Type ) << std::endl;
    std::cout << "->    contents: \"" << var << "\"." << std::endl;
}


template< typename SourceType, typename TargetType >
void    func( TargetType ( &target ) )
{
    std::cout << __FUNCTION__ << std::endl;

    SourceType  source;

    random_string( ( char * )source, sizeof( SourceType ) - 1 );

    std::cout << "-= source =-" << std::endl;
    info( source );

    std::cout << "-= target =-" << std::endl;
    info( target );

    std::memcpy( target, source,
            ( sizeof( SourceType ) < sizeof( TargetType ) ?
                sizeof( SourceType ) : sizeof( TargetType ) ) );
}


int main( )
{
    typedef char    char16[ 16 ];
    typedef char    char64[ 64 ];

    char16  c16 = "16 bytes chars.";
    char64  c64 = "64 bytes chars. There's a lot more room here...";

    std::cout << "c16 = \"" << c16 << "\"." << std::endl;
    func< char64 >( c16 );
    std::cout << "c16 = \"" << c16 << "\"." << std::endl;

    std::cout << "c64 = \"" << c64 << "\"." << std::endl;
    func< char16 >( c64 );
    std::cout << "c64 = \"" << c64 << "\"." << std::endl;

    return  0;
}

Выход:

> ./array_inner_type 
c16 = "16 bytes chars.".
func
-= source =-
->      Type is A64_c
->      Pointer size:   8
->      Number of elements:     64
->      Size of each element:   1
->      contents: "fa37JncCHryDsbzayy4cBWDxS22JjzhMaiRrV41mtzxlYvKWrO72tK0LK0e1zLO".
-= target =-
->      Type is A16_c
->      Pointer size:   8
->      Number of elements:     16
->      Size of each element:   1
->      contents: "16 bytes chars.".
c16 = "fa37JncCHryDsbza".
c64 = "64 bytes chars. There's a lot more room here...".
func
-= source =-
->      Type is A16_c
->      Pointer size:   8
->      Number of elements:     16
->      Size of each element:   1
->      contents: "Z2nOXpPIhMFSv8k".
-= target =-
->      Type is A64_c
->      Pointer size:   8
->      Number of elements:     64
->      Size of each element:   1
->      contents: "64 bytes chars. There's a lot more room here...".
c64 = "Z2nOXpPIhMFSv8k".

Снова извините, люди ...

...