this code produces 17 error C2995: function template has already been defined; there was a separate set of errors before adding the #include «set.h» header. There is a private .cpp and .h files associated with this.
/*
* File: private/set.cpp
* Last modified on Thu Jun 11 09:34:08 2009 by eroberts
* -----------------------------------------------------
* This file contains the implementation of the set.h interface.
* Because of the way C++ compiles templates, this code must be
* available to the compiler when it reads the header file.
*/
//#ifdef _set_h //original code
#ifndef _set_h
#define _set_h
#include "stdafx.h"
#include "set.h"
using namespace std;
template <typename ElemType>
Set<ElemType>::Set(int (*cmp)(ElemType, ElemType)) : bst(cmp) {
cmpFn = cmp;
}
template <typename ElemType>
Set<ElemType>::~Set() {
/* Empty */
}
template <typename ElemType>
int Set<ElemType>::size() {
return bst.size();
}
template <typename ElemType>
bool Set<ElemType>::isEmpty() {
return bst.isEmpty();
}
template <typename ElemType>
void Set<ElemType>::add(ElemType element) {
bst.add(element);
}
template <typename ElemType>
void Set<ElemType>::remove(ElemType element) {
bst.remove(element);
}
template <typename ElemType>
bool Set<ElemType>::contains(ElemType element) {
return find(element) != NULL;
}
template <typename ElemType>
ElemType *Set<ElemType>::find(ElemType element) {
return bst.find(element);
}
template <typename ElemType>
void Set<ElemType>::clear() {
bst.clear();
}
/*
* Implementation notes: Set operations
* ------------------------------------
* The code for equals, isSubsetOf, unionWith, intersectWith, and subtract
* is similar in structure. Each one uses an iterator to walk over
* one (or both) sets, doing add/remove/comparision.
*/
template <typename ElemType>
bool Set<ElemType>::equals(Set & otherSet) {
if (cmpFn != otherSet.cmpFn) {
Error("Equals: sets have different comparison functions");
}
Iterator thisItr = iterator(), otherItr = otherSet.iterator();
while (thisItr.hasNext() && otherItr.hasNext()) {
if (cmpFn(thisItr.next(), otherItr.next()) != 0) return false;
}
return !thisItr.hasNext() && !otherItr.hasNext();
}
template <typename ElemType>
bool Set<ElemType>::isSubsetOf(Set & otherSet) {
if (cmpFn != otherSet.cmpFn) {
Error("isSubsetOf: sets have different comparison functions");
}
Iterator iter = iterator();
while (iter.hasNext()) {
if (!otherSet.contains(iter.next())) return false;
}
return true;
}
template <typename ElemType>
void Set<ElemType>::unionWith(Set & otherSet) {
if (cmpFn != otherSet.cmpFn) {
Error("unionWith: sets have different comparison functions");
}
Iterator iter = otherSet.iterator();
while (iter.hasNext()) {
add(iter.next());
}
}
/*
* Implementation notes: intersectWith
* -----------------------------------
* The most obvious way to write this method (iterating over
* one set and deleting members that are not in the second)
* fails because you can't change the contents of a collection
* over which you're iterating. This code puts the elements
* to be deleted in a vector and then deletes those.
*/
template <typename ElemType>
void Set<ElemType>::intersectWith(Set & otherSet) {
if (cmpFn != otherSet.cmpFn) {
Error("intersectWith:"
" sets have different comparison functions");
}
Iterator iter = iterator();
Vector<ElemType> toDelete;
while (iter.hasNext()) {
ElemType elem = iter.next();
if (!otherSet.contains(elem)) toDelete.add(elem);
}
for (int i = 0; i < toDelete.size(); i++) {
remove(toDelete[i]);
}
}
template <typename ElemType>
void Set<ElemType>::intersect(Set & otherSet) {
if (cmpFn != otherSet.cmpFn) {
Error("intersect: sets have different comparison functions");
}
intersectWith(otherSet);
}
template <typename ElemType>
void Set<ElemType>::subtract(Set & otherSet) {
if (cmpFn != otherSet.cmpFn) {
Error("subtract: sets have different comparison functions");
}
Iterator iter = otherSet.iterator();
while (iter.hasNext()) {
remove(iter.next());
}
}
template <typename ElemType>
void Set<ElemType>::mapAll(void (*fn)(ElemType)) {
bst.mapAll(fn);
}
template <typename ElemType>
template <typename ClientDataType>
void Set<ElemType>::mapAll(void (*fn)(ElemType, ClientDataType &),
ClientDataType & data) {
bst.mapAll(fn, data);
}
/*
* Set::Iterator class implementation
* ----------------------------------
* The Iterator for Set relies on the underlying implementation of the
* Iterator for the BST class.
*/
template <typename ElemType>
Set<ElemType>::Iterator::Iterator() {
/* Empty */
}
template <typename ElemType>
typename Set<ElemType>::Iterator Set<ElemType>::iterator() {
return Iterator(this);
}
template <typename ElemType>
Set<ElemType>::Iterator::Iterator(Set *setptr) {
iterator = setptr->bst.iterator();
}
template <typename ElemType>
bool Set<ElemType>::Iterator::hasNext() {
return iterator.hasNext();
}
template <typename ElemType>
ElemType Set<ElemType>::Iterator::next() {
return iterator.next();
}
template <typename ElemType>
ElemType Set<ElemType>::foreachHook(FE_State & fe) {
if (fe.state == 0) fe.iter = new Iterator(this);
if (((Iterator *) fe.iter)->hasNext()) {
fe.state = 1;
return ((Iterator *) fe.iter)->next();
} else {
fe.state = 2;
return ElemType();
}
}
#endif
the header file
/*
* File: set.h
* Last modified on Thu Jun 11 09:17:43 2009 by eroberts
* modified on Tue Jan 2 14:34:06 2007 by zelenski
* -----------------------------------------------------
* This interface file contains the Set class template, a
* collection for efficiently storing a set of distinct elements.
*/
#ifndef _set_h
#define _set_h
#include "cmpfn.h"
#include "bst.h"
#include "vector.h"
#include "foreach.h"
/*
* Class: Set
* ----------
* This interface defines a class template that stores a collection of
* distinct elements, using a sorted relation on the elements to
* provide efficient managaement of the collection.
* For maximum generality, the Set is supplied as a class template.
* The element type is determined by the client. The client configures
* the set to hold values of a specific type, e.g. Set<int> or
* Set<studentT>. The one requirement on the element type is that the
* client must supply a comparison function that compares two elements
* (or be willing to use the default comparison function that uses
* the built-on operators < and ==).
*/
template <typename ElemType>
class Set {
public:
/* Forward references */
class Iterator;
/*
* Constructor: Set
* Usage: Set<int> set;
* Set<student> students(CompareStudentsById);
* Set<string> *sp = new Set<string>;
* -----------------------------------------
* The constructor initializes an empty set. The optional
* argument is a function pointer that is applied to
* two elements to determine their relative ordering. The
* comparison function should return 0 if the two elements
* are equal, a negative result if first is "less than" second,
* and a positive resut if first is "greater than" second. If
* no argument is supplied, the OperatorCmp template is used as
* a default, which applies the bulit-in < and == to the
* elements to determine ordering.
*/
Set(int (*cmpFn)(ElemType, ElemType) = OperatorCmp);
/*
* Destructor: ~Set
* Usage: delete sp;
* -----------------
* The destructor deallocates storage associated with set.
*/
~Set();
/*
* Method: size
* Usage: count = set.size();
* --------------------------
* This method returns the number of elements in this set.
*/
int size();
/*
* Method: isEmpty
* Usage: if (set.isEmpty())...
* ----------------------------
* This method returns true if this set contains no
* elements, false otherwise.
*/
bool isEmpty();
/*
* Method: add
* Usage: set.add(value);
* ----------------------
* This method adds an element to this set. If the
* value was already contained in the set, the existing entry is
* overwritten by the new copy, and the set's size is unchanged.
* Otherwise, the value is added and set's size increases by one.
*/
void add(ElemType elem);
/*
* Method: remove
* Usage: set.remove(value);
* -----------------------
* This method removes an element from this set. If the
* element was not contained in the set, the set is unchanged.
* Otherwise, the element is removed and the set's size decreases
* by one.
*/
void remove(ElemType elem);
/*
* Method: contains
* Usage: if (set.contains(value))...
* -----------------------------------
* Returns true if the element in this set, false otherwise.
*/
bool contains(ElemType elem);
/*
* Method: find
* Usage: eptr = set.find(elem);
* -----------------------------
* If the element is contained in this set, returns a pointer
* to that elem. The pointer allows you to update that element
* in place. If element is not contained in this set, NULL is
* returned.
*/
ElemType *find(ElemType elem);
/*
* Method: equals
* Usage: if (set.equals(set2)) . . .
* -----------------------------------
* This predicate function implements the equality relation
* on sets. It returns true if this set and set2 contain
* exactly the same elements, false otherwise.
*/
bool equals(Set & otherSet);
/*
* Method: isSubsetOf
* Usage: if (set.isSubsetOf(set2)) . . .
* --------------------------------------
* This predicate function implements the subset relation
* on sets. It returns true if all of the elements in this
* set are contained in set2. The set2 does not have to
* be a proper subset (that is, it may be equals).
*/
bool isSubsetOf(Set & otherSet);
/*
* Methods: unionWith, intersectWith, subtract
* Usage: set.unionWith(set2);
* set.intersectWith(set2);
* set.subtract(set2);
* -------------------------------
* These fmember unctions modify the receiver set as follows:
*
* set.unionWith(set2); Adds all elements from set2 to this set.
* set.intersectWith(set2); Removes any element not in set2 from this set.
* set.subtract(set2); Removes all element in set2 from this set.
*/
void unionWith(Set & otherSet);
void intersectWith(Set & otherSet);
void subtract(Set & otherSet);
/*
* Method: clear
* Usage: set.clear();
* -------------------
* This method removes all elements from this set. The
* set is made empty and will have size() = 0 after being cleared.
*/
void clear();
/*
* SPECIAL NOTE: mapping/iteration support
* ---------------------------------------
* The set supports both a mapping operation and an iterator which
* allow the client access to all elements one by one. In general,
* these are intended for _viewing_ elements and can behave
* unpredictably if you attempt to modify the set's contents during
* mapping/iteration.
*/
/*
* Method: mapAll
* Usage: set.mapAll(Print);
* -------------------------
* This method iterates through this set's contents
* and calls the function fn once for each element.
*/
void mapAll(void (*fn)(ElemType elem));
/*
* Method: mapAll
* Usage: set.mapAll(PrintToFile, outputStream);
* --------------------------------------------
* This method iterates through this set's contents
* and calls the function fn once for each element, passing
* the element and the client's data. That data can be of whatever
* type is needed for the client's callback.
*/
template <typename ClientDataType>
void mapAll(void (*fn)(ElemType elem, ClientDataType & data),
ClientDataType & data);
/*
* Method: iterator
* Usage: iter = set.iterator();
* -----------------------------
* This method creates an iterator that allows the client to
* iterate through the elements in this set. The elements are
* returned in the order determined by the comparison function.
*
* The idiomatic code for accessing elements using an iterator is
* to create the iterator from the collection and then enter a loop
* that calls next() while hasNext() is true, like this:
*
* Set<int>::Iterator iter = set.iterator();
* while (iter.hasNext()) {
* int value = iter.next();
* . . .
* }
*
* This pattern can be abbreviated to the following more readable form:
*
* foreach (int value in set) {
* . . .
* }
*
* To avoid exposing the details of the class, the definition of the
* Iterator class itself appears in the private/set.h file.
*/
Iterator iterator();
private:
#include "private/set.h"
};
#include "private/set.cpp"
#endif
Where is this going wrong
| description | title | ms.date | f1_keywords | helpviewer_keywords | ms.assetid |
|---|---|---|---|---|---|
|
Learn more about: Compiler Error C2995 |
Compiler Error C2995 |
11/04/2016 |
C2995 |
C2995 |
a57cdfe0-b40b-4a67-a95c-1a49ace4842b |
Compiler Error C2995
‘function’ : function template has already been defined
Make sure that there is only one definition for each member function of a templated class.
The following sample generates C2995:
// C2995.cpp // compile with: /c template <class T> void Test(T x){} template <class T> void Test(T x){} // C2995 template <class T> void Test2(T x){} // OK
| description | title | ms.date | f1_keywords | helpviewer_keywords | ms.assetid | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
Learn more about: Compiler errors C2900 Through C2999 |
Compiler errors C2900 Through C2999 |
06/01/2022 |
|
|
e3440738-e11b-4878-9ae3-6bc6c53ba461 |
Compiler errors C2900 Through C2999
The articles in this section of the documentation explain a subset of the error messages that are generated by the compiler.
[!INCLUDEerror-boilerplate]
Error messages
| Error | Message |
|---|---|
| Compiler error C2900 | ‘declarator‘: member function templates in WinRT classes must be ‘private’, ‘internal’ or ‘protected private’ |
| Compiler error C2901 | ‘identifier‘: A generic interface or delegate cannot be public |
| Compiler error C2902 | ‘token‘: unexpected token following ‘template/generic’, identifier expected (Obsolete in Visual Studio 2022.) |
| Compiler error C2903 | ‘identifier‘: symbol is neither a class template/generic nor a function template/generic |
| Compiler error C2904 | ‘identifier‘: name already used for a template in the current scope |
| Compiler error C2905 | Obsolete. |
| Compiler error C2906 | ‘template‘: explicit specialization requires ‘template <>’ |
| Compiler error C2907 | register argument ‘number‘ does not specify a valid register number |
| Compiler error C2908 | explicit specialization; ‘template‘ has already been instantiated |
| Compiler error C2909 | ‘identifier‘: explicit instantiation of function template requires return type |
| Compiler error C2910 | ‘function‘: cannot be explicitly specialized |
| Compiler error C2911 | ‘member‘: cannot be declared or defined in the current scope |
| Compiler error C2912 | explicit specialization ‘declaration‘ is not a specialization of a function template |
| Compiler error C2913 | explicit specialization; ‘declaration‘ is not a specialization of a class template |
| Compiler error C2914 | ‘identifier‘: cannot deduce template/generic argument as function argument is ambiguous |
| Compiler error C2915 | ‘identifier‘: ‘type‘ cannot be directly used on the published surface of a WinRT type. Use ‘Platform::Object^’ instead to pass this type |
| Compiler error C2916 | ‘identifier‘: [FlagsAttribute] must (only) be specified on a public enum with an ‘unsigned int’ underlying type |
| Compiler error C2917 | ‘identifier‘: invalid template-parameter (Obsolete in Visual Studio 2022.) |
| Compiler error C2918 | ‘identifier‘: Indexed properties cannot be used on the published surface of a WinRT type |
| Compiler error C2919 | ‘type‘: Operators cannot be used on the published surface of a WinRT type |
| Compiler error C2920 | redefinition: ‘type‘: class template/generic has already been declared as ‘declaration‘ |
| Compiler error C2921 | redefinition: ‘type‘: class template/generic is being redeclared as ‘declaration‘ |
| Compiler error C2922 | ‘interface‘: A WinRT interface cannot contain static members |
| Compiler error C2923 | ‘type‘: ‘identifier‘ is not a valid template/generic type argument for parameter ‘parameter‘ |
| Compiler error C2924 | __declspec(interrupt) routine argument not in R2 |
| Compiler error C2925 | __declspec(interrupt) routine cannot use floating-point |
| Compiler error C2926 | ‘identifier‘: a default member initializer is not allowed for a member of an anonymous struct within a union |
| Compiler error C2927 | ‘identifier‘: a function template must be called with at least one argument |
| Compiler error C2928 | explicit instantiation; ‘identifier‘ is not a function or static data member of template-class ‘class‘ |
| Compiler error C2929 | ‘declarator‘: explicit instantiation; cannot explicitly force and suppress instantiation of template-class member |
| Compiler error C2930 | ‘class‘: template-id/generic-id redefined as an enumerator of ‘enum identifier‘ |
| Compiler error C2931 | ‘class1‘: template-id/generic-id redefined as a member function of ‘class2‘ (Obsolete in Visual Studio 2022.) |
| Compiler error C2932 | ‘type‘: template-id/generic-id redefined as a data member of ‘identifier‘ (Obsolete in Visual Studio 2022.) |
| Compiler error C2933 | ‘type‘: template-id/generic-id redefined as a typedef member of ‘identifier‘ (Obsolete in Visual Studio 2022.) |
| Compiler error C2934 | ‘type‘: template-id/generic-id redefined as a nested ‘item‘ of ‘identifier‘ (Obsolete in Visual Studio 2022.) |
| Compiler error C2935 | ‘type‘: template-id/generic-id redefined as a global function (Obsolete in Visual Studio 2022.) |
| Compiler error C2936 | ‘type‘: template-id/generic-id redefined as a global data variable (Obsolete in Visual Studio 2022.) |
| Compiler error C2937 | ‘type‘: template-id/generic-id redefined as a global typedef (Obsolete in Visual Studio 2022.) |
| Compiler error C2938 | ‘identifier‘ : Failed to specialize alias template |
| Compiler error C2939 | ‘type‘: template-id/generic-id redefined as a local data variable (Obsolete in Visual Studio 2022.) |
| Compiler error C2940 | ‘type‘: template-id/generic-id redefined as a local typedef (Obsolete in Visual Studio 2022.) |
| Compiler error C2941 | ‘type‘: template-id/generic-id redefined as a local ‘item‘ (Obsolete in Visual Studio 2022.) |
| Compiler error C2942 | ‘type‘: template-id/generic-id redefined as a formal argument of a function (Obsolete in Visual Studio 2022.) |
| Compiler error C2943 | ‘type‘: template-id/generic-id redefined as a type argument of a template (Obsolete in Visual Studio 2022.) |
| Compiler error C2944 | ‘type‘: template-id/generic-id redefined as a value argument of a template (Obsolete in Visual Studio 2022.) |
| Compiler error C2945 | explicit instantiation does not refer to a template-class specialization |
| Compiler error C2946 | explicit instantiation; ‘type‘ is not a template-class specialization |
| Compiler error C2947 | expecting ‘>’ to terminate template arguments, found ‘token‘ |
| Compiler error C2948 | explicit instantiation; storage class specifier ‘specifier‘ not permitted on specialization |
| Compiler error C2949 | thread_local is not supported with /kernel |
| Compiler error C2950 | Obsolete. |
| Compiler error C2951 | template/generic declarations are only permitted at global, namespace, or class scope |
| Compiler error C2952 | ‘declaration‘: template/generic declaration missing template/generic parameter list |
| Compiler error C2953 | ‘type‘: class template has already been defined |
| Compiler error C2954 | instruction word argument not in range |
| Compiler error C2955 | ‘type‘: use of class template/generic requires template/generic argument list |
| Compiler error C2956 | usual deallocation function ‘function‘ would be chosen as placement deallocation function |
| Compiler error C2957 | ‘token‘: invalid left delimiter: expected ‘<‘ |
| Compiler error C2958 | the left delimiter found at ‘file(line_number)’ was not matched correctly |
| Compiler error C2959 | a generic class or function may not be a member of a template |
| Compiler error C2960 | Obsolete. |
| Compiler error C2961 | ‘function‘: inconsistent explicit instantiations, a previous explicit instantiation did not specify ‘argument‘ |
| Compiler error C2962 | syntax error: ‘token‘: expected template-class member function definition to end with ‘}’ |
| Compiler error C2963 | Obsolete. |
| Compiler error C2964 | Obsolete. |
| Compiler error C2965 | __declspec(specifier) is not supported with /kernel |
| Compiler error C2966 | ‘identifier1‘: must have the same __declspec(code_seg(…)) as its base class ‘identifier2‘ (Obsolete in Visual Studio 2022.) |
| Compiler error C2967 | ‘identifier‘: an overriding virtual function must have the same __declspec(code_seg(…)) as an overridden virtual function (Obsolete in Visual Studio 2022.) |
| Compiler error C2968 | ‘identifier‘: recursive alias declaration |
| Compiler error C2969 | syntax error: ‘token‘: expected member function definition to end with ‘}’ |
| Compiler error C2970 | ‘type‘: template parameter ‘parameter‘: ‘argument‘: an expression involving objects with internal linkage cannot be used as a non-type argument |
| Compiler error C2971 | ‘type‘: template parameter ‘parameter‘: ‘argument‘: a variable with non-static storage duration cannot be used as a non-type argument |
| Compiler error C2972 | ‘type‘: template parameter ‘parameter‘: the type of non-type argument is invalid |
| Compiler error C2973 | ‘template‘: invalid template argument ‘number‘ |
| Compiler error C2974 | ‘type‘: invalid template/generic argument for ‘parameter‘, type expected |
| Compiler error C2975 | ‘type‘: invalid template argument for ‘parameter‘, expected compile-time constant expression |
| Compiler error C2976 | ‘type‘: too few template/generic arguments |
| Compiler error C2977 | ‘type‘: too many template/generic arguments |
| Compiler error C2978 | syntax error: expected ‘keyword1‘ or ‘keyword2‘; found type ‘type‘; non-type parameters are not supported in generics |
| Compiler error C2979 | explicit specializations are not supported in generics |
| Compiler error C2980 | C++ exception handling is not supported with /kernel |
| Compiler error C2981 | the dynamic form of ‘keyword‘ is not supported with /kernel |
| Compiler error C2982 | ‘declaration‘: different __declspec(code_seg(…)) used: was ‘identifier1‘ now ‘identifier2‘ |
| Compiler error C2983 | ‘declaration‘: all declarations must have an identical __declspec(code_seg(…)) |
| Compiler error C2984 | Obsolete. |
| Compiler error C2985 | ‘argument‘: the argument to __declspec(code_seg(…)) must be a text section |
| Compiler error C2986 | ‘identifier‘: __declspec(code_seg(…)) can only be applied to a class or a function |
| Compiler error C2987 | a declaration cannot have both __declspec(code_seg(‘identifier‘)) and __declspec(code_seg(‘value‘)) |
| Compiler error C2988 | unrecognizable template declaration/definition |
| Compiler error C2989 | ‘class‘: class template/generic has already been declared as a non-class template/generic |
| Compiler error C2990 | ‘class‘: non-class template/generic has already been declared as a class template/generic |
| Compiler error C2991 | redefinition of template/generic parameter ‘parameter‘ |
| Compiler error C2992 | ‘class‘: invalid or missing template/generic parameter list |
| Compiler error C2993 | ‘type‘: illegal type for non-type template parameter ‘identifier‘ |
| Compiler error C2994 | unnamed class in template parameter list |
| Compiler error C2995 | ‘declaration‘: function template has already been defined |
| Compiler error C2996 | ‘function‘: recursive function template definition |
| Compiler error C2997 | ‘function‘: array bound cannot be deduced from a default member initializer |
| Compiler error C2998 | ‘declarator‘: cannot be a template definition |
| Compiler error C2999 | UNKNOWN ERROR Please choose the Technical Support command on the Visual C++ Help menu, or open the Technical Support help file for more information |
See also
C/C++ Compiler and build tools errors and warnings
Compiler errors C2000 — C3999, C7000 — C7999
Есть много вариантов решения этого вопроса, но мой ответ ничем не отвечает.
Я использую VS 2008. Я пытаюсь создать карту с помощью бинарного дерева поиска
#ifndef _map_h
#define _map_h#include<string>
using namespace std;
template <typename ValType>
class Map
{
public:
Map();
~Map();
ValType getvalue(string key);
void add(string key,ValType value);
private:
struct node{
string key;
ValType value;
node *right;
node *left;
};
node *root;
node *treeSearch(string key,node *t);
void treeEnter(string key,ValType value,node *&t);
};
#include"map.cpp"
#endif
map.cpp
#include<string>
#include<iostream>
#include"map.h"using namespace std;
template <typename ValType>
Map<ValType>::Map(){
root=NULL;
}
template <typename ValType>
Map<ValType>::~Map(){
delete root;
}template <typename ValType>
ValType Map<ValType>::getvalue(string key){
node *found=treeSearch(key,root);
if(found==NULL)
cout<<"Couldnot Found the node";
else return found->value;
}
template <typename ValType>
typename Map<ValType>::node *Map<ValType>::treeSearch(string key,node *t){
if(t==NULL) return NULL;
if(t->key==key) return t;
if(t->key>key) treeSearch(key,t->left);
else treeSearch(key,t->right);
}
template <typename ValType>
void Map<ValType>::add(string key,ValType value){
treeEnter(key,value,root);
}
template <typename ValType>
void Map<ValType>::treeEnter(string key,ValType value,node *&t){
if(t==NULL){
t->value=value;
t->key=key;
t->left=NULL;
t->right=NULL;
}
else if(t->key==key) t->value=value;
else if(t->key>key) treeEnter(key,value,t->left);
else treeEnter(key,value,t->right);
}
Ошибка: для всех функций говорится, что они уже определены.
Я слежу за онлайн-курсом в Стэнфорде, и то же самое с инструктором (она пользовалась Mac)
3
Решение
Вы включили map.h в map.cpp а также map.cpp в map.h, Включить охрану в map.h предотвратит многократное включение map.h и предотвратит бесконечное рекурсивное включение. Однако, если вы кормите map.cpp напрямую к компилятору (что вы, очевидно, пытаетесь сделать) map.h один раз и потом map.h будет включать map.cpp сам еще раз. Это то, что вызывает ошибку.
Если вы хотите реализовать свой шаблон как .cpp файл включен в .h файл, вы можете сделать это. Это странно, но его можно заставить работать. В первую очередь, если вы решили #include ваш map.cppтогда даже не пытайтесь скомпилировать map.cpp, Не кормите своих map.cpp прямо к компилятору. Кроме того, удалить #include "map.h" От этого .cpp файл. В этом нет абсолютно никакого смысла.
Ваша программа будет иметь другие файлы реализации, такие как, скажем, myprogram.cpp, который будет использовать вашу карту. Тот myprogram.cpp должны включать map.h, Тот myprogram.cpp это то, что вы будете давать компилятору. Таким образом, он будет работать как задумано. Но пытаюсь скомпилировать map.cpp напрямую приведет только к ошибкам.
Лучшей идеей было бы не помещать что-либо в .cpp файл. Либо положить все в .h файл или, если вы действительно хотите разделить его таким образом, переименуйте ваш .cpp Перейдите к чему-то другому, чтобы всем было ясно, что это не единица перевода.
4
Другие решения
В моем случае я пропустил include guard или #pragma один раз в верхней части заголовка, где я определил функцию шаблона.
1
- Forum
- General C++ Programming
- error C2995 while compiling
error C2995 while compiling
Hi,
1) When i`m trying to compile this, i`m getting this error:
node.h(48): error C2995: ‘std::ostream &operator <<(std::ostream &,const Node<T> &)’ : function template has already been defined
Any reason why ?
2) on Tree.h , there is a problem with _root = new Node<element>;
can you tell me why ?!
Movie.cpp
|
|
Movie.h
|
|
|
|
Tree.h
|
|
Last edited on
1. First is because when you have different types for T, operator<T2> << is defined for each of them. Since T2 is not the same as T, cout << Node<float> could call a << defined in Node<float> as well as the one in Node<int>, or etc. I think.. To solve this, try removing T2 and replacing it with T.
2. in _root = new Node<element>, element is not a type. This should probably be new Node<T>(element) instead.
Topic archived. No new replies allowed.
этот код генерирует 17 ошибок C2995: шаблон функции уже определен; перед добавлением заголовка #include «set.h» произошел отдельный набор ошибок. Существуют частные файлы .cpp и .h, связанные с этим.
/*
* File: private/set.cpp
* Last modified on Thu Jun 11 09:34:08 2009 by eroberts
* -----------------------------------------------------
* This file contains the implementation of the set.h interface.
* Because of the way C++ compiles templates, this code must be
* available to the compiler when it reads the header file.
*/
//#ifdef _set_h //original code
#ifndef _set_h
#define _set_h
#include "stdafx.h"
#include "set.h"
using namespace std;
template <typename ElemType>
Set<ElemType>::Set(int (*cmp)(ElemType, ElemType)) : bst(cmp) {
cmpFn = cmp;
}
template <typename ElemType>
Set<ElemType>::~Set() {
/* Empty */
}
template <typename ElemType>
int Set<ElemType>::size() {
return bst.size();
}
template <typename ElemType>
bool Set<ElemType>::isEmpty() {
return bst.isEmpty();
}
template <typename ElemType>
void Set<ElemType>::add(ElemType element) {
bst.add(element);
}
template <typename ElemType>
void Set<ElemType>::remove(ElemType element) {
bst.remove(element);
}
template <typename ElemType>
bool Set<ElemType>::contains(ElemType element) {
return find(element) != NULL;
}
template <typename ElemType>
ElemType *Set<ElemType>::find(ElemType element) {
return bst.find(element);
}
template <typename ElemType>
void Set<ElemType>::clear() {
bst.clear();
}
/*
* Implementation notes: Set operations
* ------------------------------------
* The code for equals, isSubsetOf, unionWith, intersectWith, and subtract
* is similar in structure. Each one uses an iterator to walk over
* one (or both) sets, doing add/remove/comparision.
*/
template <typename ElemType>
bool Set<ElemType>::equals(Set & otherSet) {
if (cmpFn != otherSet.cmpFn) {
Error("Equals: sets have different comparison functions");
}
Iterator thisItr = iterator(), otherItr = otherSet.iterator();
while (thisItr.hasNext() && otherItr.hasNext()) {
if (cmpFn(thisItr.next(), otherItr.next()) != 0) return false;
}
return !thisItr.hasNext() && !otherItr.hasNext();
}
template <typename ElemType>
bool Set<ElemType>::isSubsetOf(Set & otherSet) {
if (cmpFn != otherSet.cmpFn) {
Error("isSubsetOf: sets have different comparison functions");
}
Iterator iter = iterator();
while (iter.hasNext()) {
if (!otherSet.contains(iter.next())) return false;
}
return true;
}
template <typename ElemType>
void Set<ElemType>::unionWith(Set & otherSet) {
if (cmpFn != otherSet.cmpFn) {
Error("unionWith: sets have different comparison functions");
}
Iterator iter = otherSet.iterator();
while (iter.hasNext()) {
add(iter.next());
}
}
/*
* Implementation notes: intersectWith
* -----------------------------------
* The most obvious way to write this method (iterating over
* one set and deleting members that are not in the second)
* fails because you can't change the contents of a collection
* over which you're iterating. This code puts the elements
* to be deleted in a vector and then deletes those.
*/
template <typename ElemType>
void Set<ElemType>::intersectWith(Set & otherSet) {
if (cmpFn != otherSet.cmpFn) {
Error("intersectWith:"
" sets have different comparison functions");
}
Iterator iter = iterator();
Vector<ElemType> toDelete;
while (iter.hasNext()) {
ElemType elem = iter.next();
if (!otherSet.contains(elem)) toDelete.add(elem);
}
for (int i = 0; i < toDelete.size(); i++) {
remove(toDelete[i]);
}
}
template <typename ElemType>
void Set<ElemType>::intersect(Set & otherSet) {
if (cmpFn != otherSet.cmpFn) {
Error("intersect: sets have different comparison functions");
}
intersectWith(otherSet);
}
template <typename ElemType>
void Set<ElemType>::subtract(Set & otherSet) {
if (cmpFn != otherSet.cmpFn) {
Error("subtract: sets have different comparison functions");
}
Iterator iter = otherSet.iterator();
while (iter.hasNext()) {
remove(iter.next());
}
}
template <typename ElemType>
void Set<ElemType>::mapAll(void (*fn)(ElemType)) {
bst.mapAll(fn);
}
template <typename ElemType>
template <typename ClientDataType>
void Set<ElemType>::mapAll(void (*fn)(ElemType, ClientDataType &),
ClientDataType & data) {
bst.mapAll(fn, data);
}
/*
* Set::Iterator class implementation
* ----------------------------------
* The Iterator for Set relies on the underlying implementation of the
* Iterator for the BST class.
*/
template <typename ElemType>
Set<ElemType>::Iterator::Iterator() {
/* Empty */
}
template <typename ElemType>
typename Set<ElemType>::Iterator Set<ElemType>::iterator() {
return Iterator(this);
}
template <typename ElemType>
Set<ElemType>::Iterator::Iterator(Set *setptr) {
iterator = setptr->bst.iterator();
}
template <typename ElemType>
bool Set<ElemType>::Iterator::hasNext() {
return iterator.hasNext();
}
template <typename ElemType>
ElemType Set<ElemType>::Iterator::next() {
return iterator.next();
}
template <typename ElemType>
ElemType Set<ElemType>::foreachHook(FE_State & fe) {
if (fe.state == 0) fe.iter = new Iterator(this);
if (((Iterator *) fe.iter)->hasNext()) {
fe.state = 1;
return ((Iterator *) fe.iter)->next();
} else {
fe.state = 2;
return ElemType();
}
}
#endif
заголовочный файл
/*
* File: set.h
* Last modified on Thu Jun 11 09:17:43 2009 by eroberts
* modified on Tue Jan 2 14:34:06 2007 by zelenski
* -----------------------------------------------------
* This interface file contains the Set class template, a
* collection for efficiently storing a set of distinct elements.
*/
#ifndef _set_h
#define _set_h
#include "cmpfn.h"
#include "bst.h"
#include "vector.h"
#include "foreach.h"
/*
* Class: Set
* ----------
* This interface defines a class template that stores a collection of
* distinct elements, using a sorted relation on the elements to
* provide efficient managaement of the collection.
* For maximum generality, the Set is supplied as a class template.
* The element type is determined by the client. The client configures
* the set to hold values of a specific type, e.g. Set<int> or
* Set<studentT>. The one requirement on the element type is that the
* client must supply a comparison function that compares two elements
* (or be willing to use the default comparison function that uses
* the built-on operators < and ==).
*/
template <typename ElemType>
class Set {
public:
/* Forward references */
class Iterator;
/*
* Constructor: Set
* Usage: Set<int> set;
* Set<student> students(CompareStudentsById);
* Set<string> *sp = new Set<string>;
* -----------------------------------------
* The constructor initializes an empty set. The optional
* argument is a function pointer that is applied to
* two elements to determine their relative ordering. The
* comparison function should return 0 if the two elements
* are equal, a negative result if first is "less than" second,
* and a positive resut if first is "greater than" second. If
* no argument is supplied, the OperatorCmp template is used as
* a default, which applies the bulit-in < and == to the
* elements to determine ordering.
*/
Set(int (*cmpFn)(ElemType, ElemType) = OperatorCmp);
/*
* Destructor: ~Set
* Usage: delete sp;
* -----------------
* The destructor deallocates storage associated with set.
*/
~Set();
/*
* Method: size
* Usage: count = set.size();
* --------------------------
* This method returns the number of elements in this set.
*/
int size();
/*
* Method: isEmpty
* Usage: if (set.isEmpty())...
* ----------------------------
* This method returns true if this set contains no
* elements, false otherwise.
*/
bool isEmpty();
/*
* Method: add
* Usage: set.add(value);
* ----------------------
* This method adds an element to this set. If the
* value was already contained in the set, the existing entry is
* overwritten by the new copy, and the set size is unchanged.
* Otherwise, the value is added and set size increases by one.
*/
void add(ElemType elem);
/*
* Method: remove
* Usage: set.remove(value);
* -----------------------
* This method removes an element from this set. If the
* element was not contained in the set, the set is unchanged.
* Otherwise, the element is removed and the set size decreases
* by one.
*/
void remove(ElemType elem);
/*
* Method: contains
* Usage: if (set.contains(value))...
* -----------------------------------
* Returns true if the element in this set, false otherwise.
*/
bool contains(ElemType elem);
/*
* Method: find
* Usage: eptr = set.find(elem);
* -----------------------------
* If the element is contained in this set, returns a pointer
* to that elem. The pointer allows you to update that element
* in place. If element is not contained in this set, NULL is
* returned.
*/
ElemType *find(ElemType elem);
/*
* Method: equals
* Usage: if (set.equals(set2)) . . .
* -----------------------------------
* This predicate function implements the equality relation
* on sets. It returns true if this set and set2 contain
* exactly the same elements, false otherwise.
*/
bool equals(Set & otherSet);
/*
* Method: isSubsetOf
* Usage: if (set.isSubsetOf(set2)) . . .
* --------------------------------------
* This predicate function implements the subset relation
* on sets. It returns true if all of the elements in this
* set are contained in set2. The set2 does not have to
* be a proper subset (that is, it may be equals).
*/
bool isSubsetOf(Set & otherSet);
/*
* Methods: unionWith, intersectWith, subtract
* Usage: set.unionWith(set2);
* set.intersectWith(set2);
* set.subtract(set2);
* -------------------------------
* These fmember unctions modify the receiver set as follows:
*
* set.unionWith(set2); Adds all elements from set2 to this set.
* set.intersectWith(set2); Removes any element not in set2 from this set.
* set.subtract(set2); Removes all element in set2 from this set.
*/
void unionWith(Set & otherSet);
void intersectWith(Set & otherSet);
void subtract(Set & otherSet);
/*
* Method: clear
* Usage: set.clear();
* -------------------
* This method removes all elements from this set. The
* set is made empty and will have size() = 0 after being cleared.
*/
void clear();
/*
* SPECIAL NOTE: mapping/iteration support
* ---------------------------------------
* The set supports both a mapping operation and an iterator which
* allow the client access to all elements one by one. In general,
* these are intended for _viewing_ elements and can behave
* unpredictably if you attempt to modify the set contents during
* mapping/iteration.
*/
/*
* Method: mapAll
* Usage: set.mapAll(Print);
* -------------------------
* This method iterates through this set contents
* and calls the function fn once for each element.
*/
void mapAll(void (*fn)(ElemType elem));
/*
* Method: mapAll
* Usage: set.mapAll(PrintToFile, outputStream);
* --------------------------------------------
* This method iterates through this set contents
* and calls the function fn once for each element, passing
* the element and the client data. That data can be of whatever
* type is needed for the client callback.
*/
template <typename ClientDataType>
void mapAll(void (*fn)(ElemType elem, ClientDataType & data),
ClientDataType & data);
/*
* Method: iterator
* Usage: iter = set.iterator();
* -----------------------------
* This method creates an iterator that allows the client to
* iterate through the elements in this set. The elements are
* returned in the order determined by the comparison function.
*
* The idiomatic code for accessing elements using an iterator is
* to create the iterator from the collection and then enter a loop
* that calls next() while hasNext() is true, like this:
*
* Set<int>::Iterator iter = set.iterator();
* while (iter.hasNext()) {
* int value = iter.next();
* . . .
* }
*
* This pattern can be abbreviated to the following more readable form:
*
* foreach (int value in set) {
* . . .
* }
*
* To avoid exposing the details of the class, the definition of the
* Iterator class itself appears in the private/set.h file.
*/
Iterator iterator();
private:
#include "private/set.h"
};
#include "private/set.cpp"
#endif
Где это происходит неправильно
Проблема в том, что operator*() определяется внутри в шаблоне класса matrix.
Итак, когда вы определяете объект matrix, скажем, matrix<double, 1, 2>, эта функция определяется; когда вы определяете другой объект с тем же типом и разными размерами, скажем, matrix<double, 2, 1>, точно такая же функция шаблона переопределяется.
Мне кажется, что нет ничего, что требовало бы, чтобы эта функция была friend из matrix, поэтому — предложение — удалите ее внутри класса и перепишите снаружи, как показано ниже.
template <class Type, std::size_t N>
using container = std::array<Type, N>;
using size_type = std::size_t;
template <typename value_type, std::size_t Rows_lhs, std::size_t Columns_lhs,
std::size_t Rows_rhs, std::size_t Columns_rhs>
constexpr matrix<value_type, Rows_lhs, Columns_rhs> operator*(
const matrix<value_type, Rows_lhs, Columns_lhs>& lhs,
const matrix<value_type, Rows_rhs, Columns_rhs>& rhs)
{
static_assert(Columns_lhs == Rows_rhs, "Incorrect matrix for product!");
matrix<value_type, Rows_lhs, Columns_rhs> result{};
container<value_type, Rows_rhs> thatColumn{};
for (size_type j = 0; j < Columns_rhs; ++j)
{
for (size_type k = 0; k < Rows_rhs; ++k)
{
thatColumn.at(k) = rhs(k, j);
}
for (size_type i = 0; i < Rows_lhs; ++i)
{
const auto thisRow = lhs(i);
value_type summand{};
for (size_type k = 0; k < Rows_rhs; ++k)
{
summand += thisRow.at(k) * thatColumn.at(k);
}
result(i, j) = summand;
}
}
return result;
}
Если вы действительно хотите, вы можете сохранить его friend, но только объявив его внутри класса matrix
template <typename value_type, std::size_t Rows_lhs,
std::size_t Columns_lhs, std::size_t Rows_rhs,
std::size_t Columns_rhs>
friend constexpr matrix<value_type, Rows_lhs, Columns_rhs> operator*(
const matrix<value_type, Rows_lhs, Columns_lhs>& lhs,
const matrix<value_type, Rows_rhs, Columns_rhs>& rhs);
Дополнительное (не по теме) предложение: нет необходимости определять размерность матрицы четыре и налагать с помощью static_assert(), что второй (Columns_lhs) и третий (Rows_rsh) равны.
Вы можете объединить их в одном параметре шаблона (midDim, в следующем примере)
template <typename value_type, std::size_t Rows_lhs, std::size_t midDim,
std::size_t Columns_rhs>
constexpr matrix<value_type, Rows_lhs, Columns_rhs> operator*(
const matrix<value_type, Rows_lhs, midDim>& lhs,
const matrix<value_type, midDim, Columns_rhs>& rhs)
{
matrix<value_type, Rows_lhs, Columns_rhs> result{};
container<value_type, midDim> thatColumn{};
for (size_type j = 0; j < Columns_rhs; ++j)
{
for (size_type k = 0; k < midDim; ++k)
{
thatColumn.at(k) = rhs(k, j);
}
for (size_type i = 0; i < Rows_lhs; ++i)
{
const auto thisRow = lhs(i);
value_type summand{};
for (size_type k = 0; k < midDim; ++k)
{
summand += thisRow.at(k) * thatColumn.at(k);
}
result(i, j) = summand;
}
}
return result;
}
