-2

This question already has an answer here except for the fact that I read said question and still couldn't figure out what was wrong. Edit: No it doesn't the cause of this error is different.

I am trying to do this:

template<typename T>
class base
{

protected:

    base() {}

    virtual ~base() {}

    virtual void method(void* const voidp) const = 0;

};

template<typename T>
class child : public base<T> // ERROR: child is not a template type
{

public:

    child(std::vector<T> arg)
        : _arg{arg}
    {
    }

    virtual ~child() {}

    void method(void* const voidp) const
    {
        for(template std::vector<T>::const_iterator it = _arg.begin(); it != _arg.end(); ++ it)
        {
            method2(voidp, *it);
        }
    }

protected:

    std::vector<T> _arg;

};

I am slightly confused since this appears to be identical to the linked example, unless I am mistaken?

Edit: This is method2

void method2(void* const voidp, const double& arg) // second argument comes in both double and float formats
{
}

// so there is also a: void method2(void* const voidp, const float& arg)
FreelanceConsultant
  • 13,167
  • 27
  • 115
  • 225

3 Answers3

0

Not sure why you'd see

"// ERROR: child is not a template type"

However one obvious thing you're missing is typename before std::vector<T>::iterator it

Also it should be const_iterator

for(typename std::vector<T>::const_iterator it = _arg.begin(); 
     it != _arg.end(); 
      ++it)
{
    //method(voidp, *it); //<--- Assuming you've this somewhere not shown in current post
}
P0W
  • 46,614
  • 9
  • 72
  • 119
  • I don't think that's the problem... Why have you got typename before the iterator there? – FreelanceConsultant Aug 23 '15 at 19:35
  • Because `std::vector::const_iterator` is dependent type name. Also you'll have to provide a [SSCCE](http://sscce.org/) if you feel that's not the problem with current post – P0W Aug 23 '15 at 19:38
  • @user3728501 Well see [this](http://coliru.stacked-crooked.com/a/50c8f20c66ccbe61) and now fix as told – P0W Aug 23 '15 at 20:10
0

If you are having the same problem as me, it may be that you made a friend class definition elsewhere in your code? After playing around with my code on different systems with different compilers and compiler options, I fluked making it compile. I believe this was because at some point I removed a line from a file from the project, and when inspecting this file, I think it used to have a friend class definition in there. I assume that this caused the compiler to think I wasn't writing a template class? Although I am not completely convinced that this is the reason.

FreelanceConsultant
  • 13,167
  • 27
  • 115
  • 225
-1

There is no likely reason for that certain error, unless perhaps there is a class child predeclared without a class template.

One cause may be that you should initialise a member using () rather than {}:

child(std::vector<T> arg)
        : _arg{arg}
    {
    }

should be corrected to:

child(std::vector<T> arg)
        : _arg(arg)
    {
    }

It's also better to pass by const reference:

child(const std::vector<T>& arg)
        : _arg(arg)
    {
    }

However, there are a couple of other things that may be improved to aid the program:


The for loop will not compile:

for(std::vector<T>::iterator it = _arg.begin(); it != _arg.end(); ++ it)
    {
        method2(voidp, *it);
    }

T is a dependent name which means that std::vector<T>::iterator should be corrected to typename std::vector<T>::iterator. You can read more about this here.

However, std::vector<T>::iterator should also be corrected to std::vector<T>::const_iterator. As the function method is const, the const means that the function will promise not to modify any of the members of the class. However, the iterator begin() function in the vector is not const-qualified which means that the compiler does not know whether you want to modify the members or not. As a result the overload const_iterator begin() const has to be used so that the compiler explicitly knows you will not modify any members.

Another note: if you are using c++11, you can make the loop a lot shorter by using the range-for loop:

for(const auto& x : _arg)
{
    method2(voidp, x);
}

There is no need to declare public: twice in the class; once public has been declared once, everything following will be public until the compiler reaches another protected/private keyword, and vice-versa for the other keywords.

Note that the default access level for a class is private and is public for a struct. Thus your class can be slightly amended to this:

template<typename T>
class child : public base<T>
{
public:
    child(const std::vector<T>& arg)
        : _arg(arg)
    {
    }

    virtual ~child() {}

    void method(const void* voidp) const
    {
        for(typename std::vector<T>::const_iterator it = _arg.begin(); it != _arg.end(); ++ it)
        {
            method2(voidp, *it);
        }
    }

protected:
    std::vector<T> _arg;
};

Same for your base class:

template<typename T>
class base
{
protected:
    base() {}
    virtual ~base() {}
    virtual void method(const void* voidp) const = 0;
};

Be consistent with where you put the const keyword in your function declarations:

You have: void* const voidp and then const double& arg. As shown, the const keyword is inconsistently placed - one after and one before the type:

It would be better to do either: const void* voidp, const double& arg or void* const voidp, double const& arg for consistency.


To finish, I compiled the below code using MSVC and it worked fine:

template<typename T>
    class base
    {
    protected:
        base() {}
        virtual ~base() {}
        virtual void method(const void* voidp) const = 0;
    };

template<typename T>
    class child : public base<T>
    {
    public:
        child(const std::vector<T>& arg)
            : _arg(arg)
        {
        }

        virtual ~child() {}

        void method(const void* voidp) const
        {
            for(typename std::vector<T>::const_iterator it = _arg.begin(); it != _arg.end(); ++it)
            {
                method2(voidp, *it);
            }
        }

    protected:
        std::vector<T> _arg;
    };

Hope this helps:)

Joe
  • 380
  • 2
  • 6
  • To comment on some of your points: Why should I initialize with () rather than {}? – FreelanceConsultant Aug 23 '15 at 20:33
  • More comments: Yes I copied and pasted this quickly, so okay it should be const_iterator, same for public/private tags, and also template in for loop - I have modified the example to take care of this, these are not the main issues here – FreelanceConsultant Aug 23 '15 at 20:34
  • Finally I am not a believer in "auto" so I choose not to use it... I don't like that sloppy way of programming... – FreelanceConsultant Aug 23 '15 at 20:36
  • Oh, and I can't see the `const` problem? Where abouts is this? – FreelanceConsultant Aug 23 '15 at 20:37
  • @user3728501 - the `const` problem is not massively a problem as such; it is just for consistency in your code. As in it is better to constantly put const before or after the type to just make the code more consistent. – Joe Aug 23 '15 at 20:42
  • Obviously - but that's not why my code doesn't compile – FreelanceConsultant Aug 23 '15 at 20:45
  • @user3728501 - and the reason for using `()` instead of `{}` as an in-class initializer is that MSVC does not like it – Joe Aug 23 '15 at 20:46
  • @user3728501 - do you have any other classes or functions at all in your code that could perhaps cause an error? – Joe Aug 23 '15 at 20:47
  • that's a problem with your compiler not my code. I am re-writing a test project to remove everything except this class. – FreelanceConsultant Aug 23 '15 at 20:48
  • @user3728501 - sorry but I'm not too sure what the error in your code is - it seems to be completely fine and has compiled for me in MSVC... perhaps try a different compiler? – Joe Aug 23 '15 at 20:49
  • @user3728501 - sorry I couldn't help – Joe Aug 23 '15 at 20:50