#Cannot resolve symbol of templated friend function of templated class

49 messages · Page 1 of 1 (latest)

lapis crystal
#

Ay Folks,
I am currently facing an issue where I have a templated class that has a templated friend function and said friend function's symbol cannot be resolved.
The class declaration together with the friend declaration looks like this:

namespace wgen {
    template<typename T>
    class Tensor : ... {
       ...
    public:
        template<typename U>
        friend bool have_same_rank(const Tensor<U> &a, const Tensor<U> &b) {
            ...
        }
    };

Here is a snippet of the file in which i would like to access have_same_rank:

namespace wgen {
    namespace op {
        template<typename T>
        const Operator<T> add = [](std::vector<Tensor<T> > params) -> std::vector<Tensor<T> > {
            auto param1 = params[0];
            auto param2 = params[1];

            ...

            has_same_rank(param1, param2);
            
            ...
        };
    };
}

The tooling (include paths etc.) is setup right, as this file (which clearly uses Tensor) compiles when I comment out the problematic line.
So I dont think there is something wrong with my general setup.

Does anybody see anything obvious wrong with the way I am using templates, namespaces or friend functions?
If more Information is provided I can easily share.

Thanks for reading and thank you for your help in advance! (:

slate roseBOT
#

When your question is answered use !solved to mark the question as resolved.

Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question use !howto ask.

lapis crystal
#

Im baffeled because I very much declare the operator<< for the Tensor Class in the exact same way and using that works in other files.

#

I have declared the friend function inside of the class even though it is not a member function because it is a template and to my understanding you have to do it this way.

whole harbor
#

did you declare a has_same_rank anywhere else? (even if you think it is declaring the same thing)

white night
#

friend bool have_same_rank(const Tensor<U> &a, const Tensor<U> &b) {
did you mean to use Tensor instead of Tensor<U> for the first parameter?

lapis crystal
white night
#

yeah, but do you want both parameters to be Tensor<U> instead of one being Tensor<T> and the other Tensor<U>?

#

because have_same_rank is declared inside Tensor<T>, but from what you've shown it doesn't look like it's using T in any way

lapis crystal
#

Okay, I have removed the template<typename U> for have_same_rank (as well as two other functions) and the error persists.

white night
#

that's not what I meant

#

what I meant is to write ```c++
template<typename U>
friend bool have_same_rank(const Tensor<T> &a, const Tensor<U> &b) { ... }

instead of `Tensor<T>`, you can also just write `Tensor` here
#

because what I think you want to do is to take a Tensor<T> and a Tensor<U> as arguments, so that you can use it to compare the ranks and ignore the type of the tensor elements

lapis crystal
# white night what I meant is to write ```c++ template<typename U> friend bool have_same_rank(...

I see what you mean.

the code looks like this now:

namespace wgen {
    template<typename T>
    class Tensor : ... {
       ...
    public:
        // template<typename U>
        friend bool have_same_rank(const Tensor<T> &a, const Tensor<T> &b) {
            ...
        }
    };

but clion already is complaing that I might as well remove it:

namespace wgen {
    template<typename T>
    class Tensor : ... {
       ...
    public:
        // template<typename U>
        friend bool have_same_rank(const Tensor &a, const Tensor &b) {
            ...
        }
    };

But the symbol still cannot be resolved

lapis crystal
whole harbor
#

please show the exact error message

white night
lapis crystal
#
In file included from /home/nico-hubrach/Dokumente/uni/spp/wgen/libs/wgen/include/wgen/evaluator.hpp:8,
                 from /home/nico-hubrach/Dokumente/uni/spp/wgen/apps/example_usage/src/main.cpp:6:
/home/nico-hubrach/Dokumente/uni/spp/wgen/libs/wgen/include/wgen/ops/add.hpp: In instantiation of ‘wgen::Operator<double> wgen::op::add<double>’:
/home/nico-hubrach/Dokumente/uni/spp/wgen/libs/wgen/include/wgen/evaluator.hpp:150:29:   required from ‘wgen::Operator<T> wgen::Evaluator<T>::load_impl(onnx::NodeProto) [with T = double; wgen::Operator<T> = std::function<std::vector<wgen::Tensor<double>, std::allocator<wgen::Tensor<double> > >(std::vector<wgen::Tensor<double>, std::allocator<wgen::Tensor<double> > >)>]’
/home/nico-hubrach/Dokumente/uni/spp/wgen/libs/wgen/include/wgen/evaluator.hpp:88:33:   required from ‘wgen::Evaluator<T>::Evaluator(const std::string&) [with T = double; std::string = std::__cxx11::basic_string<char>]’
/home/nico-hubrach/Dokumente/uni/spp/wgen/apps/example_usage/src/main.cpp:20:41:   required from here
/home/nico-hubrach/Dokumente/uni/spp/wgen/libs/wgen/include/wgen/ops/add.hpp:16:26: error: ‘has_same_rank’ was not declared in this scope
   16 |             has_same_rank(param1, param2);
      |             ~~~~~~~~~~~~~^~~~~~~~~~~~~~~~

#

this is the exact error message

whole harbor
#

that's not a missing symbol error

#

are you not using C++20 or later?

#

if so add <> in the call

lapis crystal
#

ah wait, maybe something else is not working now that i have changed. im sorry ive pasted the error without looking. one sec

whole harbor
#

has_same_rank<>(param1, param2);

#

(although I think even for the problem I am referring to the error message should be different)

white night
#

oh lmao have_same_rank vs has_same_rank

lapis crystal
#

lol

whole harbor
lapis crystal
#

(I think it works now)

#

oh its too late

#

im sorry for wasting your time

#

thank you anyway for the quick responses

white night
#

np, these things happen

lapis crystal
#

mh im still wondering if there is any difference between the friend functions having their own template vs using the inherited template from the class.
Because the friends dont really belong to the class, ey?

#

Does it make any difference?

white night
#

you don't want to make it a template

#

because as you said, it's not a friend of the template Tensor, it's a friend of the class Tensor<T>

#

and there's no reason why a function taking two Tensor<U> would be a friend of Tensor<T> but not of Tensor<U>

#

and I think that would also mean this wouldn't compile?

lapis crystal
#

This does compile at the moment but probably just because I internally always instantiate U with T anyway:
Does not really matter anyway, your above explanation makes sense and ill remove the template.
This was still insightful. thank you!

white night
#

inside the definition of template<typename T> class Tensor, you can write Tensor instead of Tensor<T>

#

because it would be annoying to always have to repeat all template parameters

#

so that's why simply taking two const Tensor& just does the right thing

whole harbor
#

forget my suggestions from earlier btw., I got confused and stated it the wrong way around

#

before C++20 you could not write a template argument list in the call explicitly with this construct, not the other way around

#

i.e. have_same_rank<>(param1, param2); would have been ill-formed even if have_same_rank is a template

slate roseBOT
#

@lapis crystal Has your question been resolved? If so, type !solved :)

lapis crystal
#

!solved