1

I'm working on some inherited code in C++ and am trying to use 2 classes with templates as I need 2-types of each class to operate on floating point or integer data (double v uint64_t to be exact).

In the two classes that I'm trying to "templatize"(?), one inherits from the other. Data definitions needed for both are defined in the 'more base' class, some with the parameterized typename 'T', and some with resolved types (e.g. 'int') in the 'protected:' section.

The corresponding implementation (.cc) file for the more base class compiles 'ok', but the implementation file for the derived class (which is also 'templated') isn't seeing the the class data from the 1st template.

I thinking that the derived class file wants to see a resolved version of the more base class's template definition, but am not sure.

Example: more base class template file (.h) has:

template < typename T > class FieldMeter : public Meter {
...
protected:
    int numfields_;
    F *fields_;
    F total_, used_, lastused_;
...
};

'less base' class (.h) file:

template <typename T> class FieldMeterGraph : public FieldMeter <T> {
    ...
}

Problem comes in less-base class .cc file when accessing 'numfields_' or 'fields_':

fieldmetergraph.cc:51:24: error: ‘numfields_’ was not declared in this scope
  if (!heightfield_  && numfields_>0 && graphNumCols_ >0)

When both were simple classes, I didn't get the above, so it's a case where data being declared in the more base, 'templatized' class isn't accessible in the implementation of a derived template.

My terminology may be a bit off -- but it seems like this should be doable -- with "end classes" like "cpumeter" that would pass a solid data type (uint64_t) to the toplevel FieldMeterGraph template.

I'm tempted to resort to storing the type at compile time, and doing the resolution manually, at run-time like I would in 'C', but as I understand it, this should be resolvable by the compiler (g++ using C++11), at compile time.

I do have Stroustrup's 4th tomb as reference, but it seems his examples are tending toward being a bit too generic for me to correctly derive a resolvable, concrete example that g++ likes (though g++'s error messages do seem to be extraordinarily more helpful and precise compared to what I normally get in perl..)....

If someone knows how to more quickly resolve my conundrum, than my randomly trying various things that don't work, it would be appreciated! ;-)

Thanks!

  • 3
    Try this->numfields_. Without the this->, templatized base classes are not considered. Look for 2-phase lookup for details. – Sjoerd May 2 '14 at 23:50
  • @Sjoerd: That (or rather, this), does solve the compilation prob, but certainly uglifies the code. I found 2-phase at the beginning of the section on metaprogramming, maybe it will help me de-uglify again, but sprinkling this-n-thats' throughout the code doesn't seem to lend towards my goal of writing cleaner code. I.e. if the cost of double templating is extra cruft, might as well hide it in runtime resolution -- still only needs to be done once during init. Dunno. Will have to go study meta section some more.. – Astara May 3 '14 at 1:28
  • Sounds like @Sjoerd solved the problem, uglification aside. If he were to post it as an answer, would you accept it? – J Trana May 3 '14 at 3:34
  • I'd accept it on grounds of 'working', but I'll continue to search for a more elegant way, so if he wants credit for that, that's fine. I decided to copy the need class vars to const-locals to avoid the 'this' prob for now. It's more important to get something working again so I can make forward progress, then go back later for refactoring if wanted/needed... – Astara May 3 '14 at 13:29
  • BTW -- didn't mean to sound ungrateful, I was disappointed that C++ didn't handle such. – Astara May 3 '14 at 13:33
2

The C++ standard does not require to lookup non-dependent names (ie, non-dependent on the template-parameter) in dependent bases, so there is no "better" solution, apart from relying on non-standard behaviour of certain compilers.

The suggestion that you've got from @Sjoerd in the comments is appropriate, as this is an implicitly dependent name. Generally, you can use one of the following forms:

  • this->member_;
  • FieldMeter<T>::member_;

Note that while the above is identical in effect for a field, you have to carefully make the distinction when you are dealing with virtual methods, for example, FieldMeter<T>::get_member_() vs. this->get_member_(), as the former will not do a virtual dispatch.

  • Saying there is no better solution is dependent on our concepts of 'better'. Example: assigning the 'this' dependent variables to local variable storage. Since this is a derived function, it doesn't change class vars belonging to base classes, so the ones needed can be imported as const. Adding 10 lines in a block at the top removed the 20-30 this-> addons sprinkled throughout the code... It's' not a great solution, but aesthetically, it's less troublesome to read. Another option would be to pass the type at runtime and drive resolution out of a table -- conceptually '+ or -' dep:prios. – Astara May 6 '14 at 13:10
  • But as I said before, since it answered my immediate need for understanding about what the problems was, I'd mark it was answered if they wanted to propose it as an answer. That wouldn't stop me from looking for something "better" (however one defines that). Make sense? – Astara May 6 '14 at 13:14
  • @Asatra I reckon it is straightforward from the answer that the only two standard-compliant things you can do are the suggestions given. Whatever way you want to wrap those two would be just decreasing the signal to noise ratio and thus "worse". Other than eschewing templates, I don't believe you can make it less troublesome to read than this->member_. – mockinterface May 6 '14 at 13:53
  • Isn't it standard compliant to copy them to local storage (as they are read-only vars?) I.e. I can't imagine the standard prohibiting making local tmp copies of class vars ... – Astara May 6 '14 at 23:24
  • @mockinginterface: when in a normal class (not template) the vars are referenced w/o 'this->'. I (perhaps erroneously) had assumed that since I was inside a member function, the compiler was smart enough to identify references to class vars (in same class or more base classes) and make those vars 'this' relative, automatically. Am I wrong in assuming that as well?.. I.e. I would have though the former did a dispatch going up the hierarchy. Sure seems like a 'gotcha' to halfway implement templates so they don't act like classes -- transparently.... – Astara May 6 '14 at 23:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.