C++: неполный тип
У меня есть следующий код:
template<class T>
class RandomTreeNode {
public:
typedef typename RandomTreeFunction<T>::function_ptr function_ptr;
RandomTreeNode(): left(NULL), right(NULL), threshold(0.0), is_a_leaf(false), data(NULL), function(0){
}
void set_function(function_ptr function){this->function = function;}
function_ptr get_function(){ return this->function;}
void set_threshold(double threshold){this->threshold = threshold;}
double get_threshold(){return threshold;}
void create_left_child(){this->left = RandomTreeNode<T>();}
//returning references so that they can be altered in a recursive tree build algo without excessive copying
RandomTreeNode<T>& get_left_child(){return left;}
void create_right_child(){this->right = RandomTreeNode<T>();}
RandomTreeNode<T>& get_right_child(){return this->right;}
bool is_leaf(){return this->is_a_leaf;}
void mark_as_leaf(){this->is_a_leaf = true;}
const std::vector<T> get_data(){
return data;
}
void set_data(std::vector<T>& data){
this->data = data;
}
private:
RandomTreeNode<T> left;
RandomTreeNode<T> right;
double threshold;
function_ptr function;
std::vector<T> data;
bool is_a_leaf;
};
Когда я компилирую, я получаю следующее error: 'RandomTreeNode<T>::left' has incomplete type
, Есть идеи почему?
4 ответа
Потому что это тип, который вы сейчас определяете. Для типа не имеет смысла иметь элемент одного типа (для начала, он будет иметь бесконечный размер). Я думаю, что вы хотите, чтобы указатели на RandomTreeNode<T>
Это не прямые случаи.
Вы не можете объявить экземпляр класса внутри этого класса.
Здесь вы заявляете RandomTreeNode<T> left;
а также RandomTreeNode<T> right;
внутри вашей декларации RandomTreeNode
, Поэтому объявление типа не является полным.
Вы должны использовать указатели для RandomTreeNode<T>
чтобы избежать этой ошибки.
Код, который правильно компилируется (http://codepad.org/ltpxM60i)
Ниже код теперь правильно скомпилирован
**template<class T>
class RandomTreeFunction{
class function_ptr{
};
};**
template<class T>
class RandomTreeNode {
public:
typedef typename RandomTreeFunction<T>::function_ptr function_ptr;
RandomTreeNode(): left(NULL), right(NULL), threshold(0.0), is_a_leaf(false), data(NULL), function(0){
}
void set_function(function_ptr function){this->function = function;}
function_ptr get_function(){ return this->function;}
void set_threshold(double threshold){this->threshold = threshold;}
double get_threshold(){return threshold;}
void create_left_child(){this->left = RandomTreeNode<T>();}
//returning references so that they can be altered in a recursive tree build algo without excessive copying
RandomTreeNode<T>& get_left_child(){return left;}
void create_right_child(){this->right = RandomTreeNode<T>();}
RandomTreeNode<T>& get_right_child(){return this->right;}
bool is_leaf(){return this->is_a_leaf;}
void mark_as_leaf(){this->is_a_leaf = true;}
const std::vector<T> get_data(){
return data;
}
void set_data(std::vector<T>& data){
this->data = data;
}
private:
RandomTreeNode<T> left;
RandomTreeNode<T> right;
double threshold;
function_ptr function;
std::vector<T> data;
bool is_a_leaf;
};
int main(){
return 0;
}
Я думаю, что function_ptr не определен
typedef typename RandomTreeFunction<T>::**function_ptr** function_ptr;
для typename ниже приведены правила, которые применяются здесь (ссылка: - http://pages.cs.wisc.edu/~driscoll/typename.html)
Правила
typename is prohibited in each of the following scenarios:
Outside of a template definition. (Be aware: an explicit template specialization (more commonly called a total specialization, to contrast with partial specializations) is not itself a template, because there are no missing template parameters! Thus typename is always prohibited in a total specialization.)
Before an unqualified type, like int or my_thingy_t.
When naming a base class. For example, template <class C> class my_class : C::some_base_type { ... }; may not have a typename before C::some_base_type.
In a constructor initialization list.
typename is mandatory before a qualified, dependent name which refers to a type (unless that name is naming a base class, or in an initialization list).
typename is optional in other scenarios. (In other words, it is optional before a qualified but non-dependent name used within a template, except again when naming a base class or in an initialization list.)
Таким образом, вам может потребоваться определить тип для function_ptr.
Попробуйте предварительную декларацию. Напишите это в начале вашей программы в глобальном масштабе.
template<class T>
class RandomTreeNode ;
Это дает вам ошибку, потому что вы объявляете переменную того типа, который собираетесь объявить.