C++ 无法实例化模板 Class
C++ Not able to instantiate a Template Class
让我一步步来说吧。问题是我无法实例化模板 class。请帮助我哪里做错了。
我有一个模板 class 如下:
template <typename K, typename V>
class HashNodeDefaultPrint {
public:
void operator()(K key, V value) {}
};
然后我有一个属于上述模板的特定 class K = int, V = int
class HashNodePrintIntInt {
public:
void operator()(int key, int value) {
printf ("k = %d, v = %d", key, value);
}
};
同样,我还有另一个模板class如下:
template <typename K>
class defaultHashFunction {
public:
int operator()(K key) {
return 0;
}
};
同样,我有一个特定的 class 与上面的 K = int
模板相匹配
class HashFunctionInteger {
public:
int operator()(int key) {
return key % TABLE_SIZE;
}
};
现在我创建一个 HashNode 模板化 Class 如下:
template <typename K, typename V, typename F = HashNodeDefaultPrint<K, V>>
class HashNode {
public:
K key;
V value;
F printFunc;
HashNode *next;
HashNode(K key, V value, F func) {
this->key = key;
this->value = value;
next = NULL;
}
};
最后一个 HashMap 模板 class 如下:
template <typename K, typename V, typename F = defaultHashFunction<K>, typename F2 = HashNodeDefaultPrint<K,V>>
class HashMap {
private:
HashNode<K, V, F2> *table_ptr;
F hashfunc;
public:
HashMap() {
table_ptr = new HashNode<K,V, F2> [TABLE_SIZE]();
}
};
现在在 main() 中,我正在实例化 HashMap class,如下所示:
int
main(int argc, char **argv) {
HashMap<int, int, HashFunctionInteger, HashNodePrintIntInt> hmap;
return 0;
}
但我看到编译错误:
vm@ubuntu:~/src/Cplusplus/HashMap$ g++ -g -c hashmap.cpp -o hashmap.o
hashmap.cpp: In instantiation of ‘HashMap<K, V, F, F2>::HashMap() [with K = int; V = int; F = HashFunctionInteger; F2 = HashNodePrintIntInt]’:
hashmap.cpp:157:65: required from here
hashmap.cpp:107:21: error: no matching function for call to ‘HashNode<int, int, HashNodePrintIntInt>::HashNode()’
107 | table_ptr = new HashNode<K,V, F2> [TABLE_SIZE]();
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
hashmap.cpp:30:9: note: candidate: ‘HashNode<K, V, F>::HashNode(K, V, F) [with K = int; V = int; F = HashNodePrintIntInt]’
30 | HashNode(K key, V value, F func) {
| ^~~~~~~~
hashmap.cpp:30:9: note: candidate expects 3 arguments, 0 provided
hashmap.cpp:27:7: note: candidate: ‘constexpr HashNode<int, int, HashNodePrintIntInt>::HashNode(const HashNode<int, int, HashNodePrintIntInt>&)’
27 | class HashNode {
| ^~~~~~~~
hashmap.cpp:27:7: note: candidate expects 1 argument, 0 provided
hashmap.cpp:27:7: note: candidate: ‘constexpr HashNode<int, int, HashNodePrintIntInt>::HashNode(HashNode<int, int, HashNodePrintIntInt>&&)’
hashmap.cpp:27:7: note: candidate expects 1 argument, 0 provided
vm@ubuntu:~/src/Cplusplus/HashMap$
当我正确指定特定的 class 名称来定义模板变量时,这个实例化有什么问题?
template <typename K, typename V, typename F = defaultHashFunction<K>, typename
F2 = HashNodeDefaultPrint<K,V>>
class HashMap {
private:
HashNode<K, V, F2> *table_ptr;
F hashfunc;
public:
HashMap() {
table_ptr = new HashNode<K,V, F2> [TABLE_SIZE](); <----
}
};
您正在尝试新建一个没有默认构造函数的 HashNode 数组。默认构造函数被删除,因为定义了以下构造函数:
HashNode(K key, V value, F func) {
this->key = key;
this->value = value;
next = NULL;
}
您可以通过在 class 模板 HashNode
中提供 默认构造函数 来解决此错误,如下所示:
template <typename K, typename V, typename F = HashNodeDefaultPrint<K, V>>
class HashNode {
public:
HashNode(K key, V value, F func) {
this->key = key;
this->value = value;
next = NULL;
}
HashNode() = default; //DEFAULT CONSTRUCTOR ADDED
};
这是因为你写的时候需要默认构造函数:
table_ptr = new HashNode<K,V, F2> [TABLE_SIZE](); //<--- default constructor needed here
在上面的语句中new HashNode<K,V, F2> [TABLE_SIZE]()
使用了默认构造函数。
需要默认构造函数
如下例所示,我们写new Name[10]()
时会使用默认的构造函数。出于同样的原因,您需要 class 模板 HashNode
.
的默认构造函数
struct Name
{
Name()
{
std::cout<<"default constructor called"<<std::endl;
}
~Name()
{
std::cout<<"destructor called"<<std::endl;
}
};
int main() {
Name *ptr = new Name[10](); //this will use the default constructor
delete []ptr;
return 0;
}
你想的太多了:-)
如果您已经在使用模板,则可以根据需要专门化它们。那不需要新的 class 名字!
开始于:
template <typename K, typename V>
struct HashNodePrint {
void operator()(K key, V value) {}
};
// and specialize for int,int:
template<>
struct HashNodePrint<int,int> {
void operator()(int key, int value) {
printf ("k = %d, v = %d", key, value);
}
};
也一样
template <typename K>
struct HashFunction {
int operator()(K key) {
return 0;
}
};
template <>
struct HashFunction<int> {
int operator()(int ) {
return 0;
}
};
而且我希望您不再需要模板默认函数,因为您不再需要手动指定专门的函数。它们现在自动映射到专用版本。
这将在这里结束:
template <typename K, typename V>
class HashNode {
public:
K key;
V value;
HashFunction<K> printFunc;
HashNode *next;
HashNode(K key, V value) {
this->key = key;
this->value = value;
next = NULL;
}
HashNode(){}
};
但是您仍然没有 HashNode
的默认构造函数。也许您生成了一个默认值,或者您在调用中放置了一些默认值,或者完全从构造中传递了这些值。我不知道你想通过默认方式生成它来实现什么。
template <typename K, typename V >
class HashMap {
private:
HashNode<K, V> *table_ptr;
HashFunction<K> hashfunc;
public:
HashMap(/* put maybe a container type here */) {
// no idea how big your TABLE_SIZE will be.
//
table_ptr = new HashNode<K,V> [TABLE_SIZE]{ /* and forward as needed */};
}
};
int main() {
HashMap<int, int> hmap{ /* pass args maybe in container or std::initializer_list */;
return 0;
}
让我一步步来说吧。问题是我无法实例化模板 class。请帮助我哪里做错了。
我有一个模板 class 如下:
template <typename K, typename V>
class HashNodeDefaultPrint {
public:
void operator()(K key, V value) {}
};
然后我有一个属于上述模板的特定 class K = int, V = int
class HashNodePrintIntInt {
public:
void operator()(int key, int value) {
printf ("k = %d, v = %d", key, value);
}
};
同样,我还有另一个模板class如下:
template <typename K>
class defaultHashFunction {
public:
int operator()(K key) {
return 0;
}
};
同样,我有一个特定的 class 与上面的 K = int
模板相匹配class HashFunctionInteger {
public:
int operator()(int key) {
return key % TABLE_SIZE;
}
};
现在我创建一个 HashNode 模板化 Class 如下:
template <typename K, typename V, typename F = HashNodeDefaultPrint<K, V>>
class HashNode {
public:
K key;
V value;
F printFunc;
HashNode *next;
HashNode(K key, V value, F func) {
this->key = key;
this->value = value;
next = NULL;
}
};
最后一个 HashMap 模板 class 如下:
template <typename K, typename V, typename F = defaultHashFunction<K>, typename F2 = HashNodeDefaultPrint<K,V>>
class HashMap {
private:
HashNode<K, V, F2> *table_ptr;
F hashfunc;
public:
HashMap() {
table_ptr = new HashNode<K,V, F2> [TABLE_SIZE]();
}
};
现在在 main() 中,我正在实例化 HashMap class,如下所示:
int
main(int argc, char **argv) {
HashMap<int, int, HashFunctionInteger, HashNodePrintIntInt> hmap;
return 0;
}
但我看到编译错误:
vm@ubuntu:~/src/Cplusplus/HashMap$ g++ -g -c hashmap.cpp -o hashmap.o
hashmap.cpp: In instantiation of ‘HashMap<K, V, F, F2>::HashMap() [with K = int; V = int; F = HashFunctionInteger; F2 = HashNodePrintIntInt]’:
hashmap.cpp:157:65: required from here
hashmap.cpp:107:21: error: no matching function for call to ‘HashNode<int, int, HashNodePrintIntInt>::HashNode()’
107 | table_ptr = new HashNode<K,V, F2> [TABLE_SIZE]();
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
hashmap.cpp:30:9: note: candidate: ‘HashNode<K, V, F>::HashNode(K, V, F) [with K = int; V = int; F = HashNodePrintIntInt]’
30 | HashNode(K key, V value, F func) {
| ^~~~~~~~
hashmap.cpp:30:9: note: candidate expects 3 arguments, 0 provided
hashmap.cpp:27:7: note: candidate: ‘constexpr HashNode<int, int, HashNodePrintIntInt>::HashNode(const HashNode<int, int, HashNodePrintIntInt>&)’
27 | class HashNode {
| ^~~~~~~~
hashmap.cpp:27:7: note: candidate expects 1 argument, 0 provided
hashmap.cpp:27:7: note: candidate: ‘constexpr HashNode<int, int, HashNodePrintIntInt>::HashNode(HashNode<int, int, HashNodePrintIntInt>&&)’
hashmap.cpp:27:7: note: candidate expects 1 argument, 0 provided
vm@ubuntu:~/src/Cplusplus/HashMap$
当我正确指定特定的 class 名称来定义模板变量时,这个实例化有什么问题?
template <typename K, typename V, typename F = defaultHashFunction<K>, typename
F2 = HashNodeDefaultPrint<K,V>>
class HashMap {
private:
HashNode<K, V, F2> *table_ptr;
F hashfunc;
public:
HashMap() {
table_ptr = new HashNode<K,V, F2> [TABLE_SIZE](); <----
}
};
您正在尝试新建一个没有默认构造函数的 HashNode
HashNode(K key, V value, F func) {
this->key = key;
this->value = value;
next = NULL;
}
您可以通过在 class 模板 HashNode
中提供 默认构造函数 来解决此错误,如下所示:
template <typename K, typename V, typename F = HashNodeDefaultPrint<K, V>>
class HashNode {
public:
HashNode(K key, V value, F func) {
this->key = key;
this->value = value;
next = NULL;
}
HashNode() = default; //DEFAULT CONSTRUCTOR ADDED
};
这是因为你写的时候需要默认构造函数:
table_ptr = new HashNode<K,V, F2> [TABLE_SIZE](); //<--- default constructor needed here
在上面的语句中new HashNode<K,V, F2> [TABLE_SIZE]()
使用了默认构造函数。
需要默认构造函数
如下例所示,我们写new Name[10]()
时会使用默认的构造函数。出于同样的原因,您需要 class 模板 HashNode
.
struct Name
{
Name()
{
std::cout<<"default constructor called"<<std::endl;
}
~Name()
{
std::cout<<"destructor called"<<std::endl;
}
};
int main() {
Name *ptr = new Name[10](); //this will use the default constructor
delete []ptr;
return 0;
}
你想的太多了:-)
如果您已经在使用模板,则可以根据需要专门化它们。那不需要新的 class 名字!
开始于:
template <typename K, typename V>
struct HashNodePrint {
void operator()(K key, V value) {}
};
// and specialize for int,int:
template<>
struct HashNodePrint<int,int> {
void operator()(int key, int value) {
printf ("k = %d, v = %d", key, value);
}
};
也一样
template <typename K>
struct HashFunction {
int operator()(K key) {
return 0;
}
};
template <>
struct HashFunction<int> {
int operator()(int ) {
return 0;
}
};
而且我希望您不再需要模板默认函数,因为您不再需要手动指定专门的函数。它们现在自动映射到专用版本。
这将在这里结束:
template <typename K, typename V>
class HashNode {
public:
K key;
V value;
HashFunction<K> printFunc;
HashNode *next;
HashNode(K key, V value) {
this->key = key;
this->value = value;
next = NULL;
}
HashNode(){}
};
但是您仍然没有 HashNode
的默认构造函数。也许您生成了一个默认值,或者您在调用中放置了一些默认值,或者完全从构造中传递了这些值。我不知道你想通过默认方式生成它来实现什么。
template <typename K, typename V >
class HashMap {
private:
HashNode<K, V> *table_ptr;
HashFunction<K> hashfunc;
public:
HashMap(/* put maybe a container type here */) {
// no idea how big your TABLE_SIZE will be.
//
table_ptr = new HashNode<K,V> [TABLE_SIZE]{ /* and forward as needed */};
}
};
int main() {
HashMap<int, int> hmap{ /* pass args maybe in container or std::initializer_list */;
return 0;
}