0

I swear I've searched all over the Internet and SO for this exact problem, but couldn't find any solutions.

Here's the setup:

template <typename T>
class Foo {
  static bool bar;

public:
  struct Baz {
    void quux() {
      // I want to access bar here
    }
  };
  // friend typename struct Foo<T>::Baz;
  // The above works, but I'm not sure if it's what I need?
};

Is what I'm trying to do possible?

Adam Rezich
  • 3,122
  • 6
  • 31
  • 39
  • 1
    Did you try and if you did, did you get any errors? also see: http://stackoverflow.com/questions/486099/can-inner-classes-access-private-variables – NathanOliver Aug 25 '15 at 19:48
  • There's no template in that situation. I'm trying to figure out how you _refer_ to the outer class. I've tried `Foo::bar`, and `bar`, and neither works. – Adam Rezich Aug 25 '15 at 19:57
  • This works perfectly: http://ideone.com/JDKixN – imreal Aug 25 '15 at 20:00
  • @imreal But it fails when you try to call `quux`. http://coliru.stacked-crooked.com/a/3b875c16b4b527d5 – NathanOliver Aug 25 '15 at 20:06
  • @NathanOliver, it does work: http://ideone.com/JDKixN – imreal Aug 25 '15 at 20:08
  • @imreal Interesting. Both clang and g++ fail to link on coliru using `-std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out` – NathanOliver Aug 25 '15 at 20:11
  • @NathanOliver, what is the error? Probably because `bar` is not defined. What happens if you do this: http://ideone.com/JDKixN – imreal Aug 25 '15 at 20:15
  • @imreal the error is in the link I posted but I'll also post it here: `/tmp/main-86c55a.o: In function `main': main.cpp:(.text+0x2): undefined reference to `Foo::bar' clang: error: linker command failed with exit code 1 (use -v to see invocation)` – NathanOliver Aug 25 '15 at 20:16
  • Yeah like I said in the comments of the solution below, it's not compiling in Visual Studio either. When I try and call `quux`, I get `error LNK2001: unresolved external symbol "public: static bool Foo::::bar"` – Adam Rezich Aug 25 '15 at 20:21
  • @NathanOliver, in your code you don't define `Foo::bar`. @imreal does this and thus it works for them – Maksim Solovjov Aug 25 '15 at 20:29
  • Here is what I'm trying and failing to accomplish: http://ideone.com/xDj7m9 – Adam Rezich Aug 25 '15 at 20:36
  • Continuing this discussion [in chat here](http://chat.stackoverflow.com/rooms/87926/discussion-between-takua108-and-maksim-solovjov) if you guys are still interested – Adam Rezich Aug 25 '15 at 20:53

2 Answers2

2

The access is not a problem, just use Foo<T>::bar within Baz. I think that the bigger problem is that you need to allocate storage for Foo<T>::bar. This means that in your Foo.cpp file you'd have to actually instantiate all the templates you might think of using. For example:

template <typename T>
class Foo {
  static bool bar;
public:
  struct Baz {
    void quux() {
      // I want to access bar here
        Foo<T>::bar = true;
    }
  };
  static bool getBar() { return bar; }
};

// allocating storage for bars
template<>
bool Foo<int>::bar = false;
template<>
bool Foo<double>::bar = false;

int main() {
    Foo<int> fint;
    Foo<double> fouble;
    cout << Foo<int>::getBar() << " " << Foo<double>::getBar() << '\n';
    Foo<int>::Baz baz;
    baz.quux(); // alter int bar
    cout << Foo<int>::getBar() << " " << Foo<double>::getBar() << '\n';
}

Live demo

Maksim Solovjov
  • 3,147
  • 18
  • 28
  • Thanks, I'm just an idiot. I haven't used C++ in awhile and basically, I was trying to call `quux();` in the constructor for `Baz`, but I was declaring the constructor before declaring `quux`. I got so tied up in trying to wrap my mind around solving the problem I was trying to solve with template logic (and apparently, I did that part perfectly) that I forgot some C/C++ fundamentals :v Thanks for your detailed response, though! – Adam Rezich Aug 25 '15 at 20:10
  • Although, as the discussion says above, it seems to fail when you actually call `quux()` anywhere, like in the constructor for `Baz`. Why is this? – Adam Rezich Aug 25 '15 at 20:14
  • How comes? It seems to work for me: http://coliru.stacked-crooked.com/a/69b4b70af396841c – Maksim Solovjov Aug 25 '15 at 20:24
  • So in my actual use case, `bar` is a `std::list`. Here's my problem: http://ideone.com/xDj7m9 – Adam Rezich Aug 25 '15 at 20:33
  • You are still not instantiating `bar`. Here's how it works for int: http://ideone.com/TgjJ8n I'm afraid you'll have to manually specify every template you'd like to use `bar` for... – Maksim Solovjov Aug 25 '15 at 20:40
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/87926/discussion-between-takua108-and-maksim-solovjov). – Adam Rezich Aug 25 '15 at 20:47
1

"Is what I'm trying to do possible?"

No, these are still separate (though nested) and unrelated classes, by means of scope or inheritance.

// friend typename struct Foo<T>::Baz;
// The above works, but I'm not sure if it's what I need?

I'm also not so sure if this is what you actually need, but since Baz is declared in the private section of Foo<T> you can't access it unless providing a friend class declaration to (where an inner class seems to be a good choice for), or make the const member public.

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
  • It's not `static const`, it's just `static`, but this is my question: on the `// I want to access bar here` line, how do I refer to `bar`? `bar` can be public if it makes it easier, but I'd like to have it be private and set up a `friend` relationship with `Baz` so that only those `Foo` itself and `Baz` can access `bar`. I'm going to have other classes inherit from `Foo` (CRTP; `class Quux : Foo`), and I don't want the child class `Quux` to be able to access `bar`, if possible. – Adam Rezich Aug 25 '15 at 20:01
  • @takua108 It actually doesn't matter if it's actually `static const` or just `const`, it's a matter of visibility in scope. – πάντα ῥεῖ Aug 25 '15 at 20:11