带有字符串类型的c ++模板无法编译

时间:2017-03-27 03:23:04

标签: c++

我正在尝试这样做,但它无法编译..我想要做的是定义模板类专门化实现。并创建它的类型..我可以使用int类型,但我尝试使用字符串时遇到了很多麻烦..

#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;      

1 个答案:

答案 0 :(得分:0)

布莱恩问了一个使用typeid的例子。这是我前几天作为编译时多态数据存储实验的一些东西。目标是在客户端级别获得优雅的语法,将“任何”(有一些限制)放入列表中:

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

模板函数+静态变量确保每个项目只生成此字符串的一个副本。然后可以打印出类型名称,或者可以在运行时比较两个对象的指针值。我把它作为动态类型存储实验的一部分。如果有人有兴趣或接受对此方法的评论/批评,我会提供代码。基本上下面的代码创建一个“nodeBase”对象,然后创建一个“node&lt; T&gt;”这是nodeBase的子类。 nodeBase本身是一个抽象类,因此它永远不会被创建。所有真实节点都是多态节点&lt; T>类型。 nodeBase形成一个可以推送项目的堆栈,它们可以是任何类型。一个节点&lt; T>子类和一个类型&lt; T>为您尝试和存储的每种不同类型创建功能。存储类型在编译时确定,但可以在运行时从集合中正确推断类型。请注意,c ++ 17中的std :: any可能会使以下想法过时:

// 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;
}