字符串类型的 C++ 模板无法编译

c++ template with string type cannot compile

本文关键字:编译 类型 C++ 字符串      更新时间:2023-10-16

我正在尝试这样做,但它无法编译。我想做的是定义一个模板类专用化实现。并创建它的一种类型。我可以用 int 类型来做,但是当我尝试使用 string 时我遇到了很多麻烦。

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

> Bryan要求举一个使用typeid的例子。这是我前几天做的东西,作为编译时多态数据存储的实验。目标是在客户端级别获得优雅的语法,将"任何内容"(有一些限制)放入列表中:

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

模板函数 + 静态变量可确保每个项目仅生成此字符串的一个副本。然后可以打印出类型名称,或者可以在运行时比较两个对象的指针值。我将其作为动态类型存储实验的一部分。如果有人感兴趣或收到对这种方法的评论/批评,我将提供代码。基本上,下面的代码创建一个"nodeBase"对象,然后创建一个"node",它是nodeBase的子类。nodeBase 本身是一个抽象类,因此它永远不会被创建。所有实节点都是多态节点类型。nodeBase 形成一个堆栈,您可以将项目推送到其中,它们可以是任何类型的。一个节点子类,并为尝试和存储的每个不同类型创建一个 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;
}