-2

So... I was happily working on a project and then I was going to implement a friend function, which returns an object of the class after generating a random number of arbitrary size. On compilation, it's showing the error undefined reference... blah blah blah

Below is a brief mimic of the actual code/issue...

class Declaration: Random.h

// Random Declarations

#ifndef _RANDOM_H
    #define _RANDOM_H

#include <stdint.h>
#include <vector>
#include <ostream>


using uv = std::vector<uint16_t>;
using std::ostream;
using std::size_t;

class Random {
    uv data;

public:

    friend Random generate(const size_t&);
    friend ostream& operator<< (ostream&, const Random&);
};

#endif

class Definition: Random.cpp

// Random Definitions

#include "Random.h"
#include <cstdlib>

Random generate(const size_t& sz) {
    Random newRandom;
    newRandom.data.resize(sz);
    for(auto &x : newRandom.data) {
        x = rand();
    }
    return newRandom;
}

ostream& operator<< (ostream& out, const Random& random) {
    if(random.data.empty()) {
        out << '0';
    } else {
        for(auto &x : random.data) {
            out << x;
        }
    }
    return out;
}

And here is the main.cpp

#include <iostream>
#include "Random.h"

int main() {
    Random r = generate(10U); // <-- This line is throwing the error
    std::cout << r << "\n";
}

Error:

PS D:\INT\The Friend Issue> g++ main.cpp Random.cpp
main.cpp: In function 'int main()':
main.cpp:5:28: error: 'generate' was not declared in this scope
     Random r = generate(10U);
                        ^

By the way, if I declare the generate in main also then it works.

#include <iostream>
#include "Random.h"

Random generate(const std::size_t&);

int main() {
    Random r = generate(10U);
    std::cout << r << "\n";
}

No Error

PS D:\INT\The Friend Issue> g++ main.cpp Random.cpp
PS D:\INT\The Friend Issue> .\a.exe
4118467633426500191691572411478293582696224464

Any help would be thankful...

  • `#define _RANDOM_H` That name is reserved for the language implementation. By defining it, the behaviour of the program will be undefined. You should use another header guard. – eerorika Jul 15 '21 at 12:03
  • Instead of using the **C** header file `#include `, try using the **C++** header file `#include `. – Eljay Jul 15 '21 at 12:07
  • *"blah blah blah"* -- Do you really care this little about your question? – JaMiT Jul 15 '21 at 12:15
  • *By the way, if I declare the generate in main also then it works.* If you'd declare it in the header file, it'd also work. As is now, the function is a *hidden friend*, and inaccessible through ADL. – Eljay Jul 15 '21 at 12:23
  • 2
    Does this answer your question? [Friend function defined inside class not seen by compiler](https://stackoverflow.com/questions/61360176/friend-function-defined-inside-class-not-seen-by-compiler) *Note how simple the [mre] is in that question. There is only one file, hence no header guards to serve as distractions.* – JaMiT Jul 15 '21 at 12:25
  • As in the suggested duplicate, you'll need a `Random generate(const std::size_t&);` line (as you eventually added in your main.cpp) in the Random.h header. That will declare the free-standing (global) function that you eventually define in Random.cpp. – Adrian Mole Jul 15 '21 at 12:28
  • @AdrianMole yes I got it now... it was a silly mistake, due to lack of my knowledge of friend functions... Thanks... – Sp Maurya Jul 15 '21 at 12:56

1 Answers1

1

Nothing in Random.cpp tells it that generate is a function of Random. Use the notation

Random Random::generate(const size_t& sz) {
...

otherwise its just another global function. Also the public seems to indicate you want it exposed so there should be no reason for friendship. In Random.h you likely meant

static Random generate(const size_t&);

Finally nothing in main tells it that generate is a static function of Random so in main.cpp

Random r = Random::generate(10U);

If it were not static, you would need a Random to call it on. More likely you really wanted a constructor rather than generate, but that's more an organizational choice.

Abel
  • 437
  • 4
  • 7
  • 1
    OP doesn't *want* `generate` to be a member function; it is a ***friend*** of the class. – Adrian Mole Jul 15 '21 at 12:17
  • with generate as a global function, a friend, and doing the job of a constructor, I'll let the OP clarify wants... – Abel Jul 15 '21 at 12:24