Multiple inheritance/interface delegate through template function not working

  • Thread starter roman.blackhammer
  • Start date
R

roman.blackhammer

Any thoughts on why TPureVirtual:: VirtFun cannot call the second
method.
Two compilers choke on it. Actually one works, but only if not using
an 'ISO C++ Template Parser.'
Why would the language allow the first version, but not the second?

Thanks.


// -----------------------

#include <iostream>

class PureVirtual
{
public:

virtual void VirtFun() = 0;
};

template <long I, class T>
class TPureVirtual : public PureVirtual
{
public:

virtual void VirtFun()
{
// 1.
static_cast<T&>(*this).Done(I);

// 2.
static_cast<T&>(*this).TDone<I>();
}
};

class ImplVirtual : public TPureVirtual<1, ImplVirtual>,
public TPureVirtual<2, ImplVirtual>
{
public:

void
Done(long I)
{
std::cout << "ImplVirtual<" << I << ">::Done" << std::endl;
}

template <long I> void
TDone()
{
std::cout << "ImplVirtual<" << I << ">::TDone" << std::endl;
}
};

extern "C" int
main( int argc,
const char **argv )
{
ImplVirtual impl;

TPureVirtual<1, ImplVirtual> *pv1 = static_cast< TPureVirtual<1,
ImplVirtual>* >(&impl);
pv1->VirtFun();

TPureVirtual<2, ImplVirtual> *pv2 = static_cast< TPureVirtual<2,
ImplVirtual>* >(&impl);
pv2->VirtFun();

return 0;
}
 
A

Alf P. Steinbach

* (e-mail address removed):
#include <iostream>

class PureVirtual
{
public:

virtual void VirtFun() = 0;
};

template <long I, class T>
class TPureVirtual : public PureVirtual
{
public:

virtual void VirtFun()
{
// 1.
static_cast<T&>(*this).Done(I);

// 2.
static_cast<T&>(*this).TDone<I>();

}
};

class ImplVirtual : public TPureVirtual<1, ImplVirtual>,
public TPureVirtual<2, ImplVirtual>
{
public:

void
Done(long I)
{
std::cout << "ImplVirtual<" << I << ">::Done" << std::endl;
}

template <long I> void
TDone()
{
std::cout << "ImplVirtual<" << I << ">::TDone" << std::endl;
}
};

extern "C" int
main( int argc,
const char **argv )

That is an invalid signature for 'main'.

int main()

or

int main( int, char** )

{
ImplVirtual impl;

TPureVirtual<1, ImplVirtual> *pv1 = static_cast< TPureVirtual<1,
ImplVirtual>* >(&impl);
pv1->VirtFun();

TPureVirtual<2, ImplVirtual> *pv2 = static_cast< TPureVirtual<2,
ImplVirtual>* >(&impl);
pv2->VirtFun();

return 0;

'return 0' not necessary in 'main'.

Hth.,

- Alf
 
K

Kai-Uwe Bux

#include <iostream>

class PureVirtual
{
public:

virtual void VirtFun() = 0;
};

template <long I, class T>
class TPureVirtual : public PureVirtual
{
public:

virtual void VirtFun()
{
// 1.
static_cast<T&>(*this).Done(I);

// 2.
static_cast<T&>(*this).TDone<I>();

Try:

static_cast<T&>(*this).T::template TDone<I>();

The compiler does not think that TDone is a template. Thus, it tries hard to
compare a member function to an int, which does not work.

}
};

class ImplVirtual : public TPureVirtual<1, ImplVirtual>,
public TPureVirtual<2, ImplVirtual>
{
public:

void
Done(long I)
{
std::cout << "ImplVirtual<" << I << ">::Done" << std::endl;
}

template <long I> void
TDone()
{
std::cout << "ImplVirtual<" << I << ">::TDone" << std::endl;
}
};

extern "C" int
main( int           argc,
const char    **argv )
{
ImplVirtual impl;

TPureVirtual<1, ImplVirtual> *pv1 = static_cast< TPureVirtual<1,
ImplVirtual>* >(&impl);
pv1->VirtFun();

TPureVirtual<2, ImplVirtual> *pv2 = static_cast< TPureVirtual<2,
ImplVirtual>* >(&impl);
pv2->VirtFun();

return 0;
}

Best

Kai-Uwe Bux
 
R

roman.blackhammer

Thanks a million. I've never seen that syntax before, any thoughts on
where you picked it up?
 
R

Robert Bauck Hamar

Thanks a million. I've never seen that syntax before, any thoughts on
where you picked it up?

A good C++ book. Bjarne Stroustrup briefly touches the subject in "The C++
Programming Language" in section C.13.6. "C++ Templates: The Complete
Guide" by Vandevoorde and Josuttis dives deeper into the subject.

The key is this:
When parsing VirtFun, the compiler doesn't know what T is. Therefore, any
member of T is implicitly taken to be a nontemplate (and a nontype for
T::member) unless othervise stated. This means that the compiler assumes

static_cast<T&>(*this).TDone

is an object. The next symbol, <, is therefore assumed to be the less than
operator. To make the compiler think othervise, use

static_cast<T*>(this)->template TDone<...>

or

static_cast<T&>(*this).template TDone<...>

as Alf said.

This syntax must also be applied to member access to templates of which T is
a template parameter.
 
B

BobR

Alf P. Steinbach said:
* (e-mail address removed):
extern "C" int main( int argc, const char **argv )

That is an invalid signature for 'main'.

int main()
or
int main( int, char** )
{ [snip]

return 0;

'return 0' not necessary in 'main'.

Of course, but I think it dignifies it's death. <G>
And, on (old) compilers that accept 'void main()', is the 'return 0;'
guaranteed?
 
M

Marcus Kwok

BobR said:
And, on (old) compilers that accept 'void main()', is the 'return 0;'
guaranteed?

I think that since void main() is non-standard, then the C++ Standard
cannot guarantee anything about it. However, the compiler
implementation may provide its own guarantee to make sure it does The
Right Thing(tm) (for that platform).
 
J

James Kanze

I think that since void main() is non-standard, then the C++ Standard
cannot guarantee anything about it.

The standard requires a diagnostic. A standard conformant
compiler is required to issue at least a warning if void main is
used. (Many will issue an error, and fail to compile the
program.)
However, the compiler
implementation may provide its own guarantee to make sure it does The
Right Thing(tm) (for that platform).

Of course, regardless of what the compiler might or might not
do, clean programming still requires the "return 0". Say what
you mean, and mean what you say---if the function definition
says the function returns an int, you return an int.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,228
Members
46,816
Latest member
nipsseyhussle

Latest Threads

Top