c ++内部变量的奇怪模板专业化

时间:2012-02-03 16:07:40

标签: c++ templates template-specialization specialization

请考虑以下代码:

#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”并且好像它是{em>数组{{1} } 或类似的东西。

奇怪的是,它只发生在本地char64变量上。 source函数参数已正确解释。

我缺少什么? 我的代码中有误解吗?

我觉得这个问题与我在差不多一年前发布的C++ Template argument changes Reference to Pointer有关,但这个问题无论如何都没有答案,所以现在请求你帮忙。

非常感谢。

2 个答案:

答案 0 :(得分:1)

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]

这解释了为什么targetchar的数组,而sourcechar的数组数组

答案 1 :(得分:0)

抱歉,抱歉..

这真的是我的错。 事实上,解决方案比我试图做的更简单。 我刚刚看到它,感谢朋友的话。

不幸的是他没有登录,所以我只需粘贴相同代码的工作版本:

#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".

再次对不起,人们......