Inheritance of overloaded vararg methods

R

RobertEstelle

Hello,

I've been banging my head against this problem for a couple hours now
to no avail.
I'm trying to make a descendant of a class that has overloaded methods
with variable argument lists. The problem is, when my descendant class
does the same, function resolution seems to stop there without looking
at the base class.

This happens both with g++ and VS2005, so I don't suspect it's a
compiler bug.

Note that I'm just trying to inherit these methods (which are
overloaded on name), not override their implementation.

Here's a trivial example:

/////~ begin code ~/////
class T1 {};
class T2 {};

class A
{
public:
int Get(T1&, char const*, ...);
int Get(double&, char const*, ...);
};

class B : public A
{
public:
int Get(T2&, char const*, ...);
int Get(int&, char const*, ...);
};

int main(int argc, char** argv)
{
B b;
T1 t1;
// Would expect it to call A::Get(T1&, char const*, ...);
// but it doesn't; it errors out saying that B::(T2&, char
const*, ...)
// can't cast the first operator.
return b.Get(t1, "Foo", 15);
}
/////~ end code ~/////

The actual error message g++ puts out is:
vatest.cpp: In function `int main(int, char**)':
vatest.cpp:25: error: no matching function for call to `B::Get(T1&,
const char[5])'
vatest.cpp:14: note: candidates are: int B::Get(T2&, const char*, ...)
vatest.cpp:15: note: int B::Get(int&, const char*, ...)

This seems pretty puzzling to me -- it doesn't even look at the
methods A provides!
If I declare all of A's methods in B (e.g., if I were to make them
virtual and provide my own implementations in every overriding class),
resolution works just fine; but then I'm left with the problem of
implementing them all by manually passing a va_list to the
base...something that seems very hacky and dangerous.

Can anyone shed some light on this?

Thanks,
Robert Estelle
 
A

Alf P. Steinbach

* (e-mail address removed):
Hello,

I've been banging my head against this problem for a couple hours now
to no avail.
I'm trying to make a descendant of a class that has overloaded methods
with variable argument lists. The problem is, when my descendant class
does the same, function resolution seems to stop there without looking
at the base class.

This happens both with g++ and VS2005, so I don't suspect it's a
compiler bug.

Note that I'm just trying to inherit these methods (which are
overloaded on name), not override their implementation.

Here's a trivial example:

/////~ begin code ~/////
class T1 {};
class T2 {};

class A
{
public:
int Get(T1&, char const*, ...);
int Get(double&, char const*, ...);
};

class B : public A
{
public:
int Get(T2&, char const*, ...);
int Get(int&, char const*, ...);
};

int main(int argc, char** argv)
{
B b;
T1 t1;
// Would expect it to call A::Get(T1&, char const*, ...);
// but it doesn't; it errors out saying that B::(T2&, char
const*, ...)
// can't cast the first operator.
return b.Get(t1, "Foo", 15);
}
/////~ end code ~/////

The actual error message g++ puts out is:
vatest.cpp: In function `int main(int, char**)':
vatest.cpp:25: error: no matching function for call to `B::Get(T1&,
const char[5])'
vatest.cpp:14: note: candidates are: int B::Get(T2&, const char*, ...)
vatest.cpp:15: note: int B::Get(int&, const char*, ...)

This seems pretty puzzling to me -- it doesn't even look at the
methods A provides!
If I declare all of A's methods in B (e.g., if I were to make them
virtual and provide my own implementations in every overriding class),
resolution works just fine; but then I'm left with the problem of
implementing them all by manually passing a va_list to the
base...something that seems very hacky and dangerous.

Can anyone shed some light on this?

It's often a good idea to look at the FAQ before posting.

<url:
http://www.parashift.com/c++-faq-lite/strange-inheritance.html#faq-23.9>.

Cheers, & hth.,

- Alf
 
R

RobertEstelle

* (e-mail address removed):
I've been banging my head against this problem for a couple hours now
to no avail.
I'm trying to make a descendant of a class that has overloaded methods
with variable argument lists. The problem is, when my descendant class
does the same, function resolution seems to stop there without looking
at the base class.
This happens both with g++ and VS2005, so I don't suspect it's a
compiler bug.
Note that I'm just trying to inherit these methods (which are
overloaded on name), not override their implementation.
Here's a trivial example:
/////~ begin code ~/////
class T1 {};
class T2 {};
class A
{
public:
int Get(T1&, char const*, ...);
int Get(double&, char const*, ...);
};
class B : public A
{
public:
int Get(T2&, char const*, ...);
int Get(int&, char const*, ...);
};
int main(int argc, char** argv)
{
B b;
T1 t1;
// Would expect it to call A::Get(T1&, char const*, ...);
// but it doesn't; it errors out saying that B::(T2&, char
const*, ...)
// can't cast the first operator.
return b.Get(t1, "Foo", 15);
}
/////~ end code ~/////
The actual error message g++ puts out is:
vatest.cpp: In function `int main(int, char**)':
vatest.cpp:25: error: no matching function for call to `B::Get(T1&,
const char[5])'
vatest.cpp:14: note: candidates are: int B::Get(T2&, const char*, ...)
vatest.cpp:15: note: int B::Get(int&, const char*, ...)
This seems pretty puzzling to me -- it doesn't even look at the
methods A provides!
If I declare all of A's methods in B (e.g., if I were to make them
virtual and provide my own implementations in every overriding class),
resolution works just fine; but then I'm left with the problem of
implementing them all by manually passing a va_list to the
base...something that seems very hacky and dangerous.
Can anyone shed some light on this?

It's often a good idea to look at the FAQ before posting.

<url:http://www.parashift.com/c++-faq-lite/strange-inheritance.html#faq-23.9>.

Cheers, & hth.,

- Alf

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

Thanks for the link.
The solution is to put 'using A::Get;' in B's class declaration.

As an aside - had I gotten any such warning as the FAQ mentions
("Warning: Derived::f(char) hides Base::f(double)"), I would have come
across it in my searching; the problem was, I got no warning from
either VS2005 or gcc with -Wall, only the compile error I included in
my post.

Thanks again for your help.

- Robert
 
P

Pete Becker

The actual error message g++ puts out is:
vatest.cpp: In function `int main(int, char**)':
vatest.cpp:25: error: no matching function for call to `B::Get(T1&,
const char[5])'
vatest.cpp:14: note: candidates are: int B::Get(T2&, const char*, ...)
vatest.cpp:15: note: int B::Get(int&, const char*, ...)
This seems pretty puzzling to me -- it doesn't even look at the
methods A provides!

Thanks for the link.
The solution is to put 'using A::Get;' in B's class declaration.

As an aside - had I gotten any such warning as the FAQ mentions
("Warning: Derived::f(char) hides Base::f(double)"), I would have come
across it in my searching; the problem was, I got no warning from
either VS2005 or gcc with -Wall, only the compile error I included in
my post.

Right. Compilers are professional tools, not tutorials. You got the
problem exactly right: the compiler doesn't look at the member
functions that A provides. You didn't know why that was the case. Now
you do, and you'll know how to interpret similar error messages in the
future, without needing lengthy explanations from the compiler.

And note that a little experimentation would have shown that the
variable-length argument lists aren't part of the problem.
 
A

Abhishek Padmanabh

/////~ begin code ~/////
class T1 {};
class T2 {};

class A
{
public:
int Get(T1&, char const*, ...);
int Get(double&, char const*, ...);

};

class B : public A
{
public:
int Get(T2&, char const*, ...);
int Get(int&, char const*, ...);

};

int main(int argc, char** argv)
{
B b;
T1 t1;
// Would expect it to call A::Get(T1&, char const*, ...);
// but it doesn't; it errors out saying that B::(T2&, char
const*, ...)
// can't cast the first operator.
return b.Get(t1, "Foo", 15);}

/////~ end code ~/////

The actual error message g++ puts out is:
vatest.cpp: In function `int main(int, char**)':
vatest.cpp:25: error: no matching function for call to `B::Get(T1&,
const char[5])'
vatest.cpp:14: note: candidates are: int B::Get(T2&, const char*, ...)
vatest.cpp:15: note: int B::Get(int&, const char*, ...)

Are reference arguments, okay? Isn't it UB? Because, I couldn't find
anything about it in the C++ standards and C does not know about
references.
 
J

James Kanze

On Dec 15, 8:53 am, (e-mail address removed) wrote:
/////~ begin code ~/////
class T1 {};
class T2 {};
class A
{
public:
int Get(T1&, char const*, ...);
int Get(double&, char const*, ...);
};
class B : public A
{
public:
int Get(T2&, char const*, ...);
int Get(int&, char const*, ...);
};
int main(int argc, char** argv)
{
B b;
T1 t1;
// Would expect it to call A::Get(T1&, char const*, ...);
// but it doesn't; it errors out saying that B::(T2&, char
const*, ...)
// can't cast the first operator.
return b.Get(t1, "Foo", 15);}
/////~ end code ~/////
The actual error message g++ puts out is:
vatest.cpp: In function `int main(int, char**)':
vatest.cpp:25: error: no matching function for call to `B::Get(T1&,
const char[5])'
vatest.cpp:14: note: candidates are: int B::Get(T2&, const char*, ...)
vatest.cpp:15: note: int B::Get(int&, const char*, ...)
Are reference arguments okay? Isn't it UB? Because, I couldn't
find anything about it in the C++ standards and C does not
know about references.

Anything about what? §8.3.5 definitely talks about the
ellipsis, saying that it can terminate the function parameter
list. And it doesn't say anything about it introducing
additional restrictions on the previous arguments, so it
doesn't.

There is a restriction on the right most argument (parmN) if
you use va_start (§18.8/3): "If the parameter parmN is declared
with a function, array, or reference type, or with a type that
is not compatible with the type that results when passing an
argument for which there is no parameter, the behavior is
undefined." This can't affect his code, however, since the
right most argument has type char const*.
 
A

Abhishek Padmanabh

/////~ begin code ~/////
class T1 {};
class T2 {};
class A
{
public:
int Get(T1&, char const*, ...);
int Get(double&, char const*, ...);
};
class B : public A
{
public:
int Get(T2&, char const*, ...);
int Get(int&, char const*, ...);
};
int main(int argc, char** argv)
{
B b;
T1 t1;
// Would expect it to call A::Get(T1&, char const*, ...);
// but it doesn't; it errors out saying that B::(T2&, char
const*, ...)
// can't cast the first operator.
return b.Get(t1, "Foo", 15);}
/////~ end code ~/////
The actual error message g++ puts out is:
vatest.cpp: In function `int main(int, char**)':
vatest.cpp:25: error: no matching function for call to `B::Get(T1&,
const char[5])'
vatest.cpp:14: note: candidates are: int B::Get(T2&, const char*, ...)
vatest.cpp:15: note: int B::Get(int&, const char*, ...)
Are reference arguments okay? Isn't it UB? Because, I couldn't
find anything about it in the C++ standards and C does not
know about references.

Anything about what? §8.3.5 definitely talks about the
ellipsis, saying that it can terminate the function parameter
list. And it doesn't say anything about it introducing
additional restrictions on the previous arguments, so it
doesn't.

There is a restriction on the right most argument (parmN) if
you use va_start (§18.8/3): "If the parameter parmN is declared
with a function, array, or reference type, or with a type that
is not compatible with the type that results when passing an
argument for which there is no parameter, the behavior is
undefined." This can't affect his code, however, since the
right most argument has type char const*.

Yes, I was not clear about restrictions on previous arguments. So, I
believe, reference arguments to vararg functions are fine if they are
not the right most argument before (...). Thanks!
 
J

James Kanze

On Dec 15, 10:59 pm, James Kanze <[email protected]> wrote:

[...]
Yes, I was not clear about restrictions on previous arguments. So, I
believe, reference arguments to vararg functions are fine if they are
not the right most argument before (...). Thanks!

They're also fine if you don't use va_start in the function.
Not very useful, of course, but legal:).
 
R

RobertEstelle

The actual error message g++ puts out is:
vatest.cpp: In function `int main(int, char**)':
vatest.cpp:25: error: no matching function for call to `B::Get(T1&,
const char[5])'
vatest.cpp:14: note: candidates are: int B::Get(T2&, const char*, ...)
vatest.cpp:15: note: int B::Get(int&, const char*, ...)
This seems pretty puzzling to me -- it doesn't even look at the
methods A provides!
Thanks for the link.
The solution is to put 'using A::Get;' in B's class declaration.
As an aside - had I gotten any such warning as the FAQ mentions
("Warning: Derived::f(char) hides Base::f(double)"), I would have come
across it in my searching; the problem was, I got no warning from
either VS2005 or gcc with -Wall, only the compile error I included in
my post.

Right. Compilers are professional tools, not tutorials. You got the
problem exactly right: the compiler doesn't look at the member
functions that A provides. You didn't know why that was the case. Now
you do, and you'll know how to interpret similar error messages in the
future, without needing lengthy explanations from the compiler.

And note that a little experimentation would have shown that the
variable-length argument lists aren't part of the problem.

--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)

Quite right - I realized that I should have narrowed the test down to
see if the varargs actually had anything to do with it, soon after
posting. Once I got back to a computer, Alf had already found the
solution.
 

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

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,905
Latest member
Kristy_Poole

Latest Threads

Top