4

This shows the gist of it:

#include <utility>

class A {
public:
    A() { }
};

class B {
public:
    B() { }
};

typedef std::pair<A*, B*> ABPair;

int main(int argc, char* argv[])
{
    B* b = 0;               // no C2440
    ABPair p2(new A(), b);

    ABPair p1(new A(), 0);  // C2440

    return 0;
}

Is there a better way to make the p1 declaration work than just forcing a cast, e.g. ABPair p1(new A(), (B*)NULL)? This seems like it would be pretty common & that there would be a "right" way to do it .. and that casting it is not the right way.

On VS 2010, here's the full error:

1>ClCompile:
1>  test.cpp
1>c:\program files (x86)\microsoft visual studio 10.0\vc\include\utility(163): error C2440: 'initializing' : cannot convert from 'int' to 'B *'
1>          Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
1>          c:\program files (x86)\microsoft visual studio 10.0\vc\include\utility(247) : see reference to function template instantiation 'std::_Pair_base<_Ty1,_Ty2>::_Pair_base<_Ty,int>(_Other1 &&,_Other2 &&)' being compiled
1>          with
1>          [
1>              _Ty1=A *,
1>              _Ty2=B *,
1>              _Ty=A *,
1>              _Other1=A *,
1>              _Other2=int
1>          ]
1>          c:\users\charliearnold\documents\visual studio 2010\projects\test\test\test.cpp(20) : see reference to function template instantiation 'std::pair<_Ty1,_Ty2>::pair<A*,int>(_Other1 &&,_Other2 &&)' being compiled
1>          with
1>          [
1>              _Ty1=A *,
1>              _Ty2=B *,
1>              _Other1=A *,
1>              _Other2=int
1>          ]
1>c:\program files (x86)\microsoft visual studio 10.0\vc\include\utility(163): error C2439: 'std::_Pair_base<_Ty1,_Ty2>::second' : member could not be initialized
1>          with
1>          [
1>              _Ty1=A *,
1>              _Ty2=B *
1>          ]
1>          c:\program files (x86)\microsoft visual studio 10.0\vc\include\utility(167) : see declaration of 'std::_Pair_base<_Ty1,_Ty2>::second'
1>          with
1>          [
1>              _Ty1=A *,
1>              _Ty2=B *
1>          ]
1>
1>Build FAILED.
4
  • Your constructors don't match your object constructions. :) I figure this is for simplification, but a testcase ought to compile aside from the asked-about error. Additionally, "C2440" is a vendor-specific error code so error text would be more useful. Commented Jan 4, 2011 at 17:27
  • OK, you've added the text now. :) Commented Jan 4, 2011 at 17:28
  • Why do you want to use 0 instead of NULL? This may not address the main point of your question, but isn't NULL much more readable in this case? Commented Jan 4, 2011 at 17:46
  • @Jonathan: jcatki.no-ip.org:8080/fncpp/NullOrZero Commented Jan 7, 2011 at 3:02

2 Answers 2

11

Not really. nullptr will fix this in C++0x, but for now, write (B*)0.

Sign up to request clarification or add additional context in comments.

1 Comment

(You're not wrong to think that it's weird; that is why it is getting fixed :D)
5

You could use the 'make_xxx()' pattern:

#include <utility>

class A {
public:
    A() { }
};

class B {
public:
    B() { }
};

typedef std::pair<A*, B*> ABPair;

ABPair make_ABPair(A* pa, B* pb) 
{
    return ABPair(pa, pb);
}


int main(int argc, char* argv[])
{
    B* b = 0;               // no C2440
    ABPair p2(new A(), b);

    //ABPair p1(new A(), 0);  // C2440
    ABPair p1(make_ABPair(new A(), 0));

    return 0;
}

This will let you pass not only 0, but anything that's implicitly convertible to to an A* or B*.

5 Comments

Good thinking. A little more verbose than (B*)0 but arguably neater nonetheless.
I'm confused, why does MSVC allow the conversion from int to B* as an argument to make_ABPair, but not as an argument to the constructor of ABPair? GCC accepts the questioner's code with -pedantic, as does Comeau. Is this a breaking change in C++0x that MSVC already supports?
@Steve he's using a c++0x enabled library which has a perfect forwarding constructor. So it really calls a pair(A*&&, int&&) constructor, trying to initialize the B* data member using the int parameter.
@Steve: It's potentially a huge breaking change in C++0x that MSVC already supports, yes.
@Tomalak ah NVM. It says just after the "Requires: ..." paragraph: "Remarks: If U is not implicitly convertible to first_type or V is not implicitly convertible to second_type this constructor shall not participate in overload resolution.". So this just looks like a MSVC++ lib bug.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.