El Dude
El Dude

Reputation: 5618

Forward declaration mess

I am creating a multithreaded class method that needs to call compute.

void compute(const Me::MyClass<T>& c1, Me:: MyClass<T>& target,std::size_t start);

namespace Me{
    template<typename T> class MyClass{

        computeMultiThreaded(){

            MyClass<T> target = MyClass();

            std::size_t n_threads = std::thread::hardware_concurrency();

            std::vector<std::tuple<std::size_t, std::size_t>> parts = split_job(n_threads, number_jobs);
            std::vector<std::thread> threads;

            for (std::size_t ti = 0; ti < n_threads; ti++)
            {
                // , parts[ti], minCol, this, m2, returnMatrix));
                threads.push_back(std::thread(compute,parts[ti]));
            }
        }
    }
}


void compute(const Me::MyClass<T>& c1, Me:: MyClass<T>& target,std::size_t start){
...
}

Now when I try to compile this with compute defined after MyClass, Me::MyClass is not known in the first definition of compute. When I delete the first declaration, compute will not be known when creating the thread?

How can I resolve this catch 22?

error: use of undeclared identifier 'Me'

Upvotes: 0

Views: 129

Answers (3)

Mor A.
Mor A.

Reputation: 4656

The problem is that the compiler doesn't know about the existence of Me::MyClass when it reads the declaration of compute. So all we need to do is tell it that the class exists!

namespace Me {
    template<typename T> class MyClass;
}

you can later define Me::MyClass like so

template<typename T> class Me::MyClass {
// insert your class definition
};

The first snippet is a class declaration, the second is a class definition.

Upvotes: 4

Raindrop7
Raindrop7

Reputation: 3911

You can "forward-declare" the namespace and including forward declaration of your class then later do your job correctly:

namespace Me {
    template<typename T> class MyClass;
    template <class T>
    void compute(const MyClass<T>& c1, MyClass<T>& target, std::size_t start);
}

Then later:

//template<class T>
//void compute(const Me::MyClass<T>& c1, Me::MyClass<T>& target, std::size_t start); // Correct but it is already declared in namespace "Me"

Now the definition:

namespace Me {
    template<typename T> class MyClass 
    {
        void computeMultiThreaded() { // I added void here so you should add a return type
            MyClass<T> target = MyClass();

            std::size_t n_threads = std::thread::hardware_concurrency();

            std::vector<std::tuple<std::size_t, std::size_t>> parts = split_job(n_threads, number_jobs);
            std::vector<std::thread> threads;

            for (std::size_t ti = 0; ti < n_threads; ti++)
            {
                // , parts[ti], minCol, this, m2, returnMatrix));
                threads.push_back(std::thread(compute, parts[ti]));
            }
        }
    }; // you missed also the semicolon in your example
}

template <class T>
void compute(const Me::MyClass<T>& c1, Me::MyClass<T>& target, std::size_t start) {

}

I wish this works for you.

Upvotes: 0

Praetorian
Praetorian

Reputation: 109289

Declare MyClass before the declaration of compute. And compute needs to be a function template if you want it to have arbitrary MyClass<T> parameter types.

namespace Me
{
    template<typename T>
    class MyClass;
}

template<typename T>
void compute(const Me::MyClass<T>& c1, Me:: MyClass<T>& target,std::size_t start);

Upvotes: 5

Related Questions