1

[Solved]: The problem was not in template class initialization, but with code-specific issue of using undefined macro inside a template class constructor. The compiler error did not complain about undefined symbol, but was (wrongfully) related to lambdas.

I've searched for an answer but couldn't find an exact one. The closest answer is here: C++ invoke explicit template constructor but I'm not sure if that is entirely related to my question. And my question is, how can I initialize a member of structure B in initialization list if the member is a template class?

Header ClassA.h:

#ifndef _A_
#define _A_
#include <typeinfo>
#include <windows.h>

template<class Type> class A{
        int u,v;
        Type** pointer;
    public:
        A();
        A(int number);
        ~A();
        Type& operator[] (int i){
            typeid(Type);
            return *pointer[i];
        }
        Type& Get(int i)
        {
            typeid(Type);
                return *pointer[i];
        }
        Type *GetPointer(int i) 
        {
            typeid(Type);
                return pointer[i];
        }   
        Type* add ();
        Type& add(Type *element);
        Type& add(Type *element, int place);
        void expand(int NewLength);
        void swap(Type *element, int place);
        void remove(int number);
        void remove(Type *element);
        void removePointer(int number);
        void removePointer(Type *element);
    };
template<class Type>A<Type>::A(){
    u = 128;
    v = 10;
}
template<class Type>A<Type>::A(int number){
            //some thing to do with number;
            u = number;
            v = 10;
            New( pointer, Type *[u] );
        }  
template <class Type> A<Type>::~A()
{
}
template <class Type> void A<Type>::expand(int NewLength)
{

    Type **NewList = NULL;

    NewList = new Type*[NewLength];
}
template <class Type> Type* A<Type>::add ()
{

    pointer[u] = new Type;
}
template <class Type> Type& A<Type>::add(Type *element)
{
}

template <class Type> Type& A<Type>::add(Type *element, int place)
{
}
template <class Type> void A<Type>::swap(Type *element, int place)
{
}
template <class Type> void A<Type>::remove(Type *element)
{
}
template <class Type> void A<Type>::removePointer(int nume)
{
}
template <class Type> void A<Type>::removePointer(Type *element)
{
}
#endif

Header StructB.h:

#pragma once
#ifndef _B_
#define _B_

#include "ClassA.h"
struct C{
    float x,y,z;


};
struct B{
    private:
        B(){
        }
    public:
        int x,y;
        A<B*> member1;
        A<C> member2;

        B(int X,int Y) : member1(5),member2(5) {
            //initialize x,y
        }

        void Add(B* otherB){

            B** _pOtherB = new B*; (*_pOtherB) = otherB;
            member1.add(_pOtherB);

        }

    };

#endif

The compiler complains with this error (and some other errors, I can post them if nedded):

error C3493: 'number' cannot be implicitly captured because no default capture mode has been specified

Is there any way to do this, or some workaround perhaps?

Thanks in advance :D

Community
  • 1
  • 1
valdyr
  • 29
  • 4
  • 2
    What you posted compiles without error. Please post a minimal code sample that actually reproduces your problem. – Mat May 18 '14 at 08:42
  • @Mat, ok i'll edit the code – valdyr May 18 '14 at 08:46
  • 1
    The error message you received is just for Lambdas. Are you a hundert percent sure this is the error message from the above code? In that case, this is a VC++-bug. – Columbo May 18 '14 at 08:52
  • The only thing i see questionable is your initialization list for `B`, specifically, it should likely be `: x(X), y(Y), member1(5)`, and that would not invoke the error condition you describe. The private constructor for B and custom default constructor for A with no initialization lists *at all* has a putrid design smell, but certainly wouldn't trip the error you're reporting. – WhozCraig May 18 '14 at 08:54
  • @Arcoth, yes the other errors also indicate that they are for Lambdas. When I change "B(int X,int Y) : member1(5) { }" to just "B(int X,int Y){ }" the compiler doesn't complain and compiles everything without errors... – valdyr May 18 '14 at 08:59
  • @WhozCraig I've added x(X) and y(Y) to the initialization list but there are the same errors still... And all of the errors are for lambdas... – valdyr May 18 '14 at 09:07
  • @valdyr .. and **none** of the code you posted has lamdas. So your problem is not reproducible in that context of the posted code. Where is `Type` **used** in the code you chose *not* to post for the class template `A` ? – WhozCraig May 18 '14 at 09:09
  • I' have posted a more complete code. The problem is I can't post the exact code... There is also a struct C, which is used as Type argument for template class A – valdyr May 18 '14 at 09:46
  • Try to compile now! It seems it has something to do with New( pointer, Type *[u] ) which is in constructor A(int number). In my infinite stupidity I can't see the reason why it won't compile... – valdyr May 18 '14 at 09:55
  • seems like my problem has nothing to do with template class in initialization lists as I thought at first, but with New() which is in A(int number). – valdyr May 18 '14 at 10:05
  • What are you trying to accomplish with "New( pointer, Type *[u] );"? – jhoffman0x May 18 '14 at 10:07
  • @jhoffman0x, well the code for class A isn't mine, but my guess is it will allocate memory and store pointer to that memory to A::pointer, (similar to this: pointer = new Type*[u]) – valdyr May 18 '14 at 10:13

1 Answers1

2

Either the code you've given us isn't complete, or it is broken. This line:

New(pointer, Type *[u]);

seems to be referencing either some missing member method or global function, or it is simply invalid. The error message is kinda cryptic, but that's C++ for you.

I'm going to assume that New is some kind of macro, because no normal function (even a templated one) can take this sort of type definition as a parameter. You've not given us the definition of New, so there's no way we can tell. It is probably the absense of this macro (maybe a wrapper for some sort of memory debugging system?) that is causing the crazy error.

If I replace the New line with this:

pointer = new Type*[u];

the code compiles fine.

Rook
  • 5,734
  • 3
  • 34
  • 43
  • yes, I've allso found it's problem with that line... The problem is I can't find declaration of New() in entire project, but the compiler didn't complain about undefined method/function, instead it pointed out some other error (namely labda related errors...) – valdyr May 18 '14 at 10:39
  • Its the price you pay for using a language who's grammar is a bit... intractable. Anyway, `New` must be a macro. Possibly the person you inherited the code from had the macro defined somewhere in their VS configuration and not in their code or project, or perhaps you just have incomplete code. – Rook May 18 '14 at 10:42
  • Even more puzzling is the fact that I have started a blank new project in VS and used just the code posted in my question and still the compiler complains about lambda errors, and not because New() is undefined... – valdyr May 18 '14 at 10:44
  • Yes, I allso think It's a macro... My question should be deleted to avoid confusion. – valdyr May 18 '14 at 10:48
  • Nah, its always good to leave stuff as a warning to other people ;-) – Rook May 18 '14 at 10:50
  • Incidentally, compiling under GCC also gives some lambda capture warnings, but also gives `error: ‘New’ was not declared in this scope`. So the poor error reporting is partially a problem with C++, and partially a problem with Visual Studio. – Rook May 18 '14 at 10:51
  • I have also tested the code in Visual Studio 2008 (which doesn't got support for lambdas), it gives a more proper error. I think the poor error reporting for this case is with Visual Studio 2012. Thanks for checking in GCC... – valdyr May 18 '14 at 11:11