I am trying to write two constructors for the same class. One takes an
iterator and so is a template. The other takes a particular type by
reference to const.
class Foo {
public:
template<typename InputIterator>
Foo(InputIterator i);
Foo(const Bar & b);
When I do this, trying to construct a Foo from a Bar calls the
template, not the constructor from a Bar. This is in VC++ 7.0. And it
does not matter which I declare first.
Questions: Is this a compiler oddity or standard behavior? Is there any
way around it?
I know a semi-solution. When I pass them both by value or both by
reference to const, it works.
template<typename InputIterator>
Foo(InputIterator i);
Foo(Bar b);
or
template<typename InputIterator>
Foo(const InputIterator & i);
Foo(const Bar & b);
But I would prefer not to do that. Any other ideas/thoughts? 2 1836
Glenn G. Chappell wrote: I am trying to write two constructors for the same class. One takes an iterator and so is a template. The other takes a particular type by reference to const.
class Foo { public: template<typename InputIterator> Foo(InputIterator i); Foo(const Bar & b);
When I do this, trying to construct a Foo from a Bar calls the template, not the constructor from a Bar. This is in VC++ 7.0. And it does not matter which I declare first.
Questions: Is this a compiler oddity or standard behavior? Is there any way around it?
It is a standard behaviour. If you construct from an object, the template
one will win because the compiler will figure out what type it is from
the argument and there will be no conversion required. A const reference
requires "binding to".
I know a semi-solution. When I pass them both by value or both by reference to const, it works.
template<typename InputIterator> Foo(InputIterator i); Foo(Bar b);
or
template<typename InputIterator> Foo(const InputIterator & i); Foo(const Bar & b);
But I would prefer not to do that. Any other ideas/thoughts?
You can add a fake argument to the one you don't care to keep implicit:
template<typename InputIterator>
Foo(InputIterator i, int);
Of course, you will have to stick an extra argument when constructing
an object from the iterator...
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
* Glenn G. Chappell: I am trying to write two constructors for the same class. One takes an iterator and so is a template. The other takes a particular type by reference to const.
class Foo { public: template<typename InputIterator> Foo(InputIterator i); Foo(const Bar & b);
When I do this, trying to construct a Foo from a Bar calls the template, not the constructor from a Bar. This is in VC++ 7.0. And it does not matter which I declare first.
With both MSVC 7.1 and MingW g++ 3.4.2, the following program,
#include <iostream> // std::cout
#include <ostream> // operator<<, std::endl
void say( char const s[] ) { std::cout << s << std::endl; }
class Bar {};
class Foo
{
public:
template< typename InputIterator >
Foo( InputIterator ) { say( "Template" ); }
Foo( Bar const& ) { say( "Non-template" ); }
};
int main()
{
Bar b;
Foo f( b );
}
says "Non-template", but when passed an argument of type derived from
Bar it says "Template".
Questions: Is this a compiler oddity or standard behavior?
Off-hand I'd say a compiler oddity for the case of pure Bar argument.
Is there any way around it?
Best, use the solution you outline below. Second best (but should be
done anyway), upgrade the compiler. Third, perhaps use SFINAE
(Substitution Failure Is Not An Error).
The Boost library has a ready-made SFINAE solution. The following might
give you an idea if you don't want to use Boost:
#include <iostream> // std::cout
#include <ostream> // operator<<, std::endl
void say( char const s[] ) { std::cout << s << std::endl; }
class Bar {};
class BarD: public Bar {};
template< typename InputIterator >
struct NonBar { typedef InputIterator T; };
template<> struct NonBar<Bar>;
template<> struct NonBar<BarD>;
class Foo
{
public:
template< typename InputIterator >
Foo( InputIterator, typename NonBar<InputIterator>::T* = 0 )
{ say( "Template" ); }
Foo( Bar const& ) { say( "Non-template" ); }
};
int main()
{
Bar b;
BarD bd;
Foo f( b );
Foo fd( bd );
Foo fi( 666 );
}
with output "Non-template, non-template, template" with both MSVC 7.1
and MingW g++ 3.4.2.
Of course to make it more general you'd have to check sub-subclass
relationship and somehow make that part of the SFINAE checking (not sure
whether that's possible, perhaps the Boost solution does that), and
anyway, as I wrote above, consider solutions (1) and (2) first.
Solution (1):
I know a semi-solution. When I pass them both by value or both by reference to const, it works.
template<typename InputIterator> Foo(InputIterator i); Foo(Bar b);
or
template<typename InputIterator> Foo(const InputIterator & i); Foo(const Bar & b);
But I would prefer not to do that. Any other ideas/thoughts?
I think this is the cleanest solution.
Why do you want to avoid this?
--
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? This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: Paul MG |
last post by:
Hi
Template partial specialization always seems like a fairly
straightforward concept - until I try to do it :).
I am trying to implement the input sequence type (from Stroustrup
section...
|
by: SainTiss |
last post by:
Hi,
If you've got a template class with lots of methods,
and then you've got a type which works with the template,
except for one method...
What you need to do there is specialize the...
|
by: Agent Mulder |
last post by:
Hi group,
I have a problem with partial template specialization. In the code
below I have a template struct Music with one method, play(),
and three kinds of music, Jazz, Funk and Bach. When I...
|
by: Jeff |
last post by:
/* --------------------------------------------------------------------------
Hello,
I was experimenting with class templates and specializing member
functions and came across a simple problem...
|
by: Nathanael D. Noblet |
last post by:
Hello,
I'm having a problem with a templated class. I have
two template classes Node and List. Everything works fine when
the type for List is an object and not a pointer
ie:"List<Object>...
|
by: Dave |
last post by:
Hello all,
Consider this function template definition:
template<typename T>
void foo(T) {}
If foo is never called, this template will never be instantiated.
Now consider this explicit...
|
by: NKOBAYE027 |
last post by:
FIRST POST
Hi All: I'm trying to write a simple specialization before moving on to
something a bit more complex - always a good idea in my case, at least. :o)
I'm trying to adapt the example...
|
by: Marek Vondrak |
last post by:
Hello.
I have written the following program and am curious why it prints "1" "2".
What are the exact effects of explicitly providing function template
parameters at the call? Is the second...
|
by: Barry |
last post by:
The following code compiles with VC8
but fails to compiles with Comeau online,
I locate the standard here:
An explicit specialization of any of the following:
|
by: abir |
last post by:
i have a template as shown
template<typename Sclass Indexer{};
i want to have a specialization for std::vector both const & non const
version.
template<typename T,typename Aclass...
|
by: Charles Arthur |
last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
|
by: BarryA |
last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
|
by: nemocccc |
last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
|
by: Sonnysonu |
last post by:
This is the data of csv file
1 2 3
1 2 3
1 2 3
1 2 3
2 3
2 3
3
the lengths should be different i have to store the data by column-wise with in the specific length.
suppose the i have to...
|
by: Hystou |
last post by:
There are some requirements for setting up RAID:
1. The motherboard and BIOS support RAID configuration.
2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
|
by: Hystou |
last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
|
by: Oralloy |
last post by:
Hello folks,
I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>".
The problem is that using the GNU compilers,...
|
by: jinu1996 |
last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
|
by: agi2029 |
last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
| |