2017-03-27 16 views
0

私はこれをしようとしていますが、コンパイルできません。私がしたいのは、テンプレートクラスの特殊化の実装を定義することです。そしてブライアンはを求め文字列型のC++テンプレートはコンパイルできません

#include <iostream> 

using namespace std; 

template <char const *str> 
struct X 
{ 
}; 
constexpr char global_string[] = "String"; 

template<> 
struct X<global_string> 
{ 
    typedef int mytype; 

    const char *GetString() const 
    { 
     return global_string; 
    } 
}; 


constexpr char version_use[] = "String"; 
int main() 
{ 
    using X1= X<version_use> ; 
    X1::mytype t = 1; 
    //X1 x; 
    //cout<<x.GetString() << " " << t; 
} 
sh-4.2$ g++ -std=c++11 -o main *.cpp                                                
main.cpp: In function 'int main()':                                                 
main.cpp:27:5: error: 'mytype' is not a member of 'X1 {aka X<((const char*)(& version_use))>}'                                  
    X1::mytype t = 1;                                                    
    ^                                                       
main.cpp:27:16: error: expected ';' before 't'                                              
    X1::mytype t = 1;  
+0

'global_string'と' version_use'は異なるものであるため、ポインタへのディケイ時に、それらは異なるアドレスを指す。すなわち、それらは異なる値を有する。 – songyuanyao

+0

これは私が文字列テンプレート型で何をしたいのですか? –

+0

Cスタイルの文字列(つまり 'char *')の内容に基づいてそれを行う場合は、不可能です。 – songyuanyao

答えて

0

..私はint型でそれを行うことができますが、私は、文字列をしようとしたとき、私は多くの問題を持って...それの型を作成typeidを使用する例先日、私はコンパイル時の多形データ記憶の実験として何かを作った。目標は、リストに(一部制限あり)「何を」置くためにクライアントレベルでエレガントな構文を取得することでした:

template <typename T> const char* Type() 
{ 
    static const char *s = typeid(T).name(); 
    return s; 
} 

テンプレート機能+静的変数は、プロジェクトごとに生成され、この文字列のコピーは1つだけありますが保証されます。次に、型名を出力するか、2つのオブジェクトのポインタの値を実行時に比較することができます。私はダイナミック型の記憶の実験の一部としてこれを作った。誰かが興味を持ったり、このアプローチのコメント/批評を受けたりする場合は、コードを提供します。基本的に以下のコードは "nodeBase"オブジェクトを作成し、nodeBaseの子クラスである "node < T>"を作成します。 nodeBase自体は抽象クラスなので、決して作成されません。すべての実ノードは、多形ノード< T>型です。 nodeBaseはアイテムをプッシュできるスタックを形成し、どのタイプでも構いません。 1つのノード< T>子クラスと1つのタイプ< T>関数は、試して保存するタイプごとに作成されます。コンパイル時に型の格納が決定されますが、実行時にコレクションから型を正しく推論することができます。それはstd ::を注意してください任意のC++では17は以下のアイデアが時代遅れになるかもしれない:

// stores type string and used to compare types at runtime 
template <typename T> const char* Type() { static const char *s = typeid(T).name(); return s; } 

// nodeBase parent class, with virtual function Data 
struct nodeBase 
{ 
    nodeBase *next = 0; 
    const char *type; 
    int size; 
    virtual ~nodeBase() {}; 
    virtual void *Data() = 0; 
}; 

// child class for data structures that have copy constructors 
template <typename T> struct node : public nodeBase // template for storing regular structs and stuff 
{ 
    T data; 
    node(T _data) : data(_data) 
    { 
     type = Type<T>(); 
     size = sizeof(data); 
    } 
    ~node() {} 
    void *Data() { 
     return &data; 

    } 
}; 

// template specialization just for "char *" strings 
template <> struct node<const char*> : public nodeBase // this is a template specialization just for strings 
{ 
    char *data; 
    node(const char *_data) 
    { 
     type = Type<const char*>(); 
     size = strlen(_data) + 1; 
     data = new char[size]; 
     strcpy_s(data, size, _data); 
    } 
    ~node() { delete data; } 
    void *Data() { return data; } 
}; 

// create function makes node<T> and returns base class pointer 
template <typename T> nodeBase *create(T data) { return new node<T>(data); } 

template specialization of "create" function to pack in std::strings as just "char *" strings 
template <> nodeBase *create<std::string>(std::string data) { return create(data.c_str()); } 

// this function needs to expand according to what types you want to retrieve 
void displayNode(nodeBase *n) 
{ 
    if (!n) return; 

    std::cout << n->type << "(" << n->size << " bytes) "; 

    if (n->type == Type<float>()) 
    { 
     std::cout << " = " << *(float *)(n->Data()) << std::endl; 
    } 
    else if (n->type == Type<double>()) 
    { 
     std::cout << " = " << *(double *)(n->Data()) << std::endl; 
    } 
    else if (n->type == Type<char const *>()) 
    { 
     std::cout << " = " << (const char *)n->Data() << std::endl; 
    } 
    else 
    { 
     std::cout << " = " << *(int *)n->Data() << std::endl; 
    } 
} 

// really simple stack implementation for storing a list 
class stack 
{ 
public: 
    nodeBase *head = nullptr; 
    unsigned int count; 

    ~stack() 
    { 
     while (head) 
     { 
      nodeBase *temp = head; 
      head = head->next; 
      delete temp; 
     } 
    } 

    // custom templated push function 
    template <typename T> void push(T data) 
    { 
     nodeBase *new_node = create(data); 
     new_node->next = head; 
     head = new_node; 
     count++; 
    } 

    // quick and dirty [] operator to access the values for the print test 
    nodeBase *operator[](int index) 
    { 
     nodeBase *node = head; 

     while (index > 0 && node != nullptr) 
     { 
      node = node->next; 
      index--; 
     } 

     return node; 
    } 
}; 

struct Cat { int whiskers = 1000; }; 

int test_list_multi() 
{ 
    stack list1; 

    // pushes a bunch of junk into the list to show it really can store just about anything without needing obtuse syntax 
    list1.push(44); 
    list1.push(2.0423423432f); 
    list1.push("drugs"); 
    list1.push(std::string("hello")); 
    list1.push(bool(true)); 
    list1.push(2.4545); 
    list1.push('a'); 
    list1.push(short(66)); 
    list1.push([] { int a, b; }); 
    list1.push([] { int a; }); 
    struct Dog { int legs[4]{ 9,9,9,9 }; char tail{ 't' }; }; 
    Dog dog; 
    Cat cat; 
    list1.push(dog); 
    list1.push(cat); 

    std::cout << "count = " << list1.count << std::endl; 

    // go through the list and display details for each node including type and value 
    for (int i = 0; i < list1.count; ++i) 
    { 
     displayNode(list1[i]); 
    } 

    std::cin.ignore(); 
    std::cin.get(); 
    return 0; 
} 
関連する問題