Search code examples
c++struct

How to define a struct member function which returns another struct


I have written a simple worksheet program to convert between cartesian coordinates and polar coordinates. When compiled, an error is displayed.

Code:

#include <iostream>
#include <cmath>
#include <iomanip>

#define PI 3.14159

struct Polar;

struct Vector2;

struct Polar{
    double r, theta;

    Vector2 toCartesian(){
        return {r*cos(theta*PI/180), r*sin(theta*PI/180)};
    }  
};

struct Vector2{
    double x,y;

    Polar toPolar(){
        return {sqrt(x*x + y*y), atan(y/x)};
    }
};



int main(){
    std::cout << "Enter Polar coordinates in form of R theta to convert to cartesian: ";
    Polar P;
    std::cin >> P.r >> P.theta;
    Vector2 Pcord;
    Pcord = P.toCartesian();
    std::cout << std::fixed << std::setprecision(3) << "(x,y) = " << Pcord.x << " " << Pcord.y;
    std::cin.get();
    return 0;
}

Error message:

exe.cpp: In member function 'Vector2 Polar::toCartesian()':
exe.cpp:14:26: error: return type 'struct Vector2' is incomplete
     Vector2 toCartesian(){
                          ^
exe.cpp: In function 'int main()':
exe.cpp:34:27: error: no match for 'operator=' (operand types are 'Vector2' and 'void')
     Pcord = P.toCartesian();
                           ^
exe.cpp:19:8: note: candidate: constexpr Vector2& Vector2::operator=(const Vector2&)
 struct Vector2{
        ^~~~~~~
exe.cpp:19:8: note:   no known conversion for argument 1 from 'void' to 'const Vector2&'
exe.cpp:19:8: note: candidate: constexpr Vector2& Vector2::operator=(Vector2&&)
exe.cpp:19:8: note:   no known conversion for argument 1 from 'void' to 'Vector2&&'*

What is the issue here? At first, I thought this was because the compiler didn't know struct Vector2 exists when going through struct Polar, similar to calling a function declared below from another function, so I used a forward declaration, but the issue is not resolved.


Solution

  • A forward declaration merely tells the compiler that a type exists, but not what that type looks like, so the compiler doesn't known what is needed to create instances of that type.

    You are trying to create a Vector2 instance before the compiler knows what Vector2 contains. That is why the error message says Vector2 is an incomplete type.

    To accomplish what you are trying to do, you must separate the declaration and definition of Polar::toCartesian() so that you can fully define Vector2 before you can then create an instance of it, eg:

    #include <iostream>
    #include <cmath>
    #include <iomanip>
    
    #define PI 3.14159
    
    struct Vector2;
    
    struct Polar{
        double r, theta;
    
        Vector2 toCartesian();
    };
    
    struct Vector2{
        double x,y;
    
        Polar toPolar(){
            return {sqrt(x*x + y*y), atan(y/x)};
        }
    };
    
    Vector2 Polar::toCartesian(){
        return {r*cos(theta*PI/180), r*sin(theta*PI/180)};
    }
    
    int main(){
        std::cout << "Enter Polar coordinates in form of R theta to convert to cartesian: ";
        Polar P;
        std::cin >> P.r >> P.theta;
        Vector2 Pcord;
        Pcord = P.toCartesian();
        std::cout << std::fixed << std::setprecision(3) << "(x,y) = " << Pcord.x << " " << Pcord.y;
        std::cin.get();
        return 0;
    }
    

    Online Demo