2012-02-03 1 views
0

Рассмотрим следующий код:C++ странно шаблон специализации на внутренней переменной

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

static void random_string(char *s, const int len) 
{ 
    static const char alphanum[] = 
     "" 
     "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 ] для меня и НКУ не является тоже самое.

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

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

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

Я чувствую, что эта проблема связана с этим C++ Template argument changes Reference to Pointer, отправленная мной почти год назад, но этот вопрос не имел ответа, так что теперь я прошу вас, пожалуйста, за любую помощь.

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

+0

Вы написали слишком много кода, пожалуйста, будьте более краткими, удалив из кода неинтересные части. – vulkanino

ответ

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].

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

0

К сожалению, извините ..

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

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

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


static void random_string(char *s, const int len) 
{ 
    static const char alphanum[] = 
     "" 
     "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". 

К сожалению опять же, люди ...