2012-07-10 2 views
0

Koch의 Snowflake를 구현하려고합니다. 연습용으로 일반적인 목록을 만들었지 만 몇 가지 문제가 있습니다. > 그것은 단지 하나의 값으로 노드의 데이터를 설정합니다목록에 템플릿 오류가 있습니다.

Error 1 error C2440: '=' : cannot convert from 'GLfloat []' to 'float [2]' 13 

난 그냥 목록 <GLfloat*로 초기화되었다 : 여기

#include <stdlib.h> 
#include <stdio.h> 
#include <math.h> 
#include <gl/glut.h> 


template <typename T> class Node { 
public: 
    T data; 
    Node<T> *next; 
    Node<T>(T d) { 
     next = NULL; 
     data = d; 
    } 
}; 
template <typename T> class List { 
    Node<T> *head; 
    int size; 
public: 
    List() { 
     head = NULL; 
     size = 0; 
    } 
    void append(T data){ 
     if(head == NULL) { 
      head = new Node<T>(data); 
     } else { 
      Node<T> *n = head; 
      while(n->next != NULL) { 
       n = n->next; 
      } 
      n->next = new Node<T>(data); 
     } 
     size++; 
    } 
    void appendAll(List<T> data) { 
     if(data.getHead() == NULL) 
      return; 
     Node<T> *n = data.getHead(); 
     append(n->data); 
     while(n->next != NULL){ 
      append(n->next->data); 
      n = n->next; 
     } 
    } 
    Node<T>* getHead(){ return head; } 
}; 
void myinit(); 
void display(); 
void draw_snowflake(); 
List<GLfloat[2]> divide_snowflake(GLfloat A[2], GLfloat B[2], int n); 

GLfloat tri[3][2] = {{-1.0, -0.58}, {1.0, -0.58}, {0.0, 1.15}}; 
List<GLfloat[2]> snow; 
int n; 


int main(int argc, char **argv) { 
    n = 0; 
    glutInit(&argc, argv); 
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); 
    glutInitWindowSize(500,500); 
    glutCreateWindow("Koch Snowflake"); 
    glutDisplayFunc(display); 
    myinit(); 
    glutMainLoop(); 

    return EXIT_SUCCESS; 
} 

void myinit(){ 
    // Initialize OpenGL 
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    gluOrtho2D(-2.0, 2.0, -2.0, 2.0); 
    glMatrixMode(GL_MODELVIEW); 
    glClearColor(1.0, 1.0, 1.0, 1.0); 
    glColor3f(0.0,0.0,0.0); 

    // Initialize list of line_loop 
    snow.append(tri[0]); 
    snow.append(tri[1]); 
    snow.append(tri[2]); 
} 

void display(){ 
    glClear(GL_COLOR_BUFFER_BIT); 
    glBegin(GL_LINE_LOOP); 
    draw_snowflake(); 
    glEnd(); 
    glFlush(); 
} 

void draw_snowflake(){ 
    List<GLfloat[2]> temp; 
    temp.append(snow.getHead()->data); 
    Node<GLfloat[2]> *curr = snow.getHead(); 
    while(curr->next != NULL) { 
     temp.appendAll(divide_snowflake(curr->data, curr->next->data, n)); 
     temp.append(curr->next->data); 
     curr = curr->next; 
    } 
    temp.appendAll(divide_snowflake(curr->data, snow.getHead()->data, n)); 

    Node<GLfloat[2]> *ptr = temp.getHead(); 
    printf("\n>Drawing %f, %f", ptr->data[0], ptr->data[1]); 
    glVertex2fv(ptr->data); 
    while(ptr->next != NULL) { 
     printf("\n>Drawing %f, %f", ptr->next->data[0], ptr->next->data[1]); 
     glVertex2fv(ptr->next->data); 
     ptr = ptr->next; 
    } 
} 

List<GLfloat[2]> divide_snowflake(GLfloat A[2], GLfloat B[2], int n) { 
    GLfloat A_Mid[2] = {A[0] + (B[0] - A[0])/3, 
         A[1] + (B[1] - A[1])/3}; 
    GLfloat Mid[2] = {A[0] + (B[0] - A[0])/2, 
         A[1] + (B[1] - A[1])/2}; 
    GLfloat B_Mid[2] = {B[0] - (B[0] - A[0])/3, 
         B[1] - (B[1] - A[1])/3}; 
    GLfloat Peak[2] = {Mid[0] + (Mid[1] - B_Mid[1]) * sqrt(3.0), 
         Mid[1] + (Mid[0] - A_Mid[0]) * sqrt(3.0)}; 

    List<GLfloat[2]> temp; 
    if(n > 0) temp.appendAll(divide_snowflake(A, A_Mid, n-1)); 
    temp.append(A_Mid); 
    if(n > 0) temp.appendAll(divide_snowflake(A_Mid, Peak, n-1)); 
    temp.append(Peak); 
    if(n > 0) temp.appendAll(divide_snowflake(Peak, B_Mid, n-1)); 
    temp.append(B_Mid); 
    if(n > 0) temp.appendAll(divide_snowflake(B_Mid, B, n-1)); 
    return temp; 
} 

내가 점점 오전 오류입니다 반대로, 나는 포인트를 원한다. 연습 목적으로 계속 일반 목록을 사용하고 싶습니다.

+2

왜'std :: list'를 사용하지 않으시겠습니까? 일반적인 목록이며 작동합니다. – mfontanini

+0

@mfontanini : 맨 위에 "연습"이라고 쓰여 있습니다. 모든 프로그래머가 장래에 라이브러리를 계속 쓸 수있을 정도로 숙련 된 1 일째부터 라이브러리를 기본값으로 사용한다면? –

+0

@EdS. 오, 나는 항상 그 : /. 네, 제 자신의 구조를 만들었습니다. 나는 그가 "일반 목록"을 원했기 때문에 목록을 작성하고 있다고 생각했습니다. – mfontanini

답변

1

비 제너릭 목록, 즉 GLFloat[2]으로 작업 한 목록을 사용하면 코드가 어떻게 될지 생각해 봅시다. 그것은 GLFloat*을 취

class Node { 
public: 
    GLFloat[2] data; 
    Node *next; 
    Node(GLFloat[2] d) { 
     next = NULL; 
     data = d; 
    } 
}; 

중요한 지금주의 Node의 생성자가 실제로 배열을하지 않는다는 것입니다 생각 : 여기 노드 코드입니다. 이것은 C++이 작동하는 방식입니다. (당신이 인수 유형은 템플릿 매개 변수에 의존 할 때 이상하게도 나에게,이 또한 작동하는 방식이다. 분명히, array is also treated as a pointer 다음)

는 이제 data = d;을 수행하여, 시도

는에 GLFloat*을 할당 GLFloat[2]. 이것은 의미있는 것이 아닙니다. 포인터를 가져 와서 그 값을 배열에 넣을 수는 없습니다. 명시 적으로 d[0]data[0]에, d[1]을 에 넣을 수는 있지만 목록이 아닌 배열 유형에서는 더 이상 작동하지 않으므로 매우 일반적이지는 않습니다.

수행 할 수있는 작업은 무엇입니까? 글쎄, 한 가지 해결책은 배열에 대한 목록을 전문화하는 것입니다. 코드는

template <typename T, std::size_t N> 
class Node<T[N]> { 
public: 
    T data; 
    Node<T> *next; 
    Node<T>(T d) { 
     next = NULL; 
     for (std::size_t i = 0; i < N; ++i) 
      data[i] = d[i]; 
    } 
}; 

그러나,이 코드 중복이 많이 발생할 수 있습니다 ... 같은 것을보고, 당신이 요소를 반환 할 수있는 방법과 같은 추가 문제로 연결됩니다.

대신 내 조언은 std::pair<GLFloat, GLFloat>을 사용하는 것입니다. 이것은 귀하의 목록과 함께 작동합니다. 또는 임의의 수의 요소를 저장하려는 경우 std::array을 사용할 수 있습니다.

그리고 나는이 모든 것에 대해 논평하고 있지만, Node 클래스 템플릿을 구현 세부 사항이므로 List 클래스 템플릿으로 옮길 수 있습니다. getHead() 기능을 제공하지 않아야합니다. 캡슐화를 깨뜨리지 않는 것이 좋습니다. 반복을 위해 iterator 클래스와 begin()end() 함수를 제공하십시오. 한 가지 가능한 구현의 라인을 따라 것 : 이것은 당신이 지금까지했던 모든 것을위한 충분한 인터페이스를 제공 할 것, 그리고 더 깨끗한 것

struct iterator { 
    friend List; 
    private: 
    Node* current; 
    iterator(Node* c) : current(c) {} 
    public: 
    iterator& operator++() { 
     current = current->next; 
     return *this; 
    } 

    friend bool operator==(iterator const& lhs, iterator const& rhs) { 
     return lhs.current == rhs.current; 
    } 

    T& operator*() { 
     return current->data; 
    } 

    T* operator->() { 
     return &current->data; 
    } 
}; 

. 보다 완벽한 인터페이스를 구현하려면 불행히도 많은 상용구가 필요합니다. 이 시점에서 간단한 std::list으로 전환 할 수 있습니다.

+0

'T & d'는 작동 할 것이고'T = GLfloat [2]'의 결과가 나온다. 왜냐하면 _arrays_에는 값 의미가 없기 때문입니다 (_copyied_ 할 수 없음). –

+0

'T & d'는'Node' 생성자가 참조로 배열을 취할 것이지만 할당하는 것은 여전히 ​​작동하지 않는다는 것을 의미합니다. –

관련 문제