Condition operator "?:" and LPCTSTR in function header
Asked Answered
B

3

8

Maybe anyone can explain this to me:

bool Func1(LPCTSTR sData)
{
    if (sData) { ... }
}

And I called the function like this:

CString str = _T("");
Func1((str.IsEmpty() ? NULL : str));

And 'sData' inside function is never NULL, it is allways empty string but not NULL, why? Eddited code like this:

LPCTSTR strNull = NULL;
Func1((str.IsEmpty() ? strNull : str));

In this case it works correct.

Bronchus answered 7/9, 2016 at 14:2 Comment(1)
Func1((str.IsEmpty() ? NULL : str)); doesn't compile on VS2015, I get Error C2446 ':': no conversion from 'CString' to 'int' ...Latten
T
5

This is caused by the need to convert both the second and third operands to a common type.
(The result can't have different types depending on whether the condition is true or not.)

The first parameter is equivalent to

str.IsEmpty() ? CString(NULL) : str

since NULL doesn't have a type that you convert a CString to.
And CString(NULL) constructs an empty CString.

The second is equivalent to

str.IsEmpty() ? strNull : (LPCTSTR) str

since CString is convertible to LPCTSTR but not the other way around.

Inlining the cast,

    str.IsEmpty() ? (LPCTSTR) NULL : str

should give the same effect as the second.

Thermobarometer answered 7/9, 2016 at 14:27 Comment(2)
And I'm still confused how the CString c'tor is resolved in the expression CString(NULL). There are several c'tors that take pointer arguments. How does the compiler pick one (and which one is it)?Gruesome
I get it now: All c'tors taking a single pointer argument are explicit, except for the one taking a const XCHAR*.Gruesome
D
5

The conditional operator converts its second and third arguments to a type that's common to the two of them. I don't know the details of CString, so this is just a guess, but it looks like the conditional operator converts NULL to a CString to match the type of the third argument, and passes that, through an implicit conversion to LPCTSTR, to the function.

Dragonet answered 7/9, 2016 at 14:10 Comment(1)
CString does have an implicit conversion operator (CSimpleStringT::operator PCXSTR). I still don't quite follow, how the CStringT::CStringT constructor is resolved. There are more than one that matches a NULL pointer.Gruesome
T
5

This is caused by the need to convert both the second and third operands to a common type.
(The result can't have different types depending on whether the condition is true or not.)

The first parameter is equivalent to

str.IsEmpty() ? CString(NULL) : str

since NULL doesn't have a type that you convert a CString to.
And CString(NULL) constructs an empty CString.

The second is equivalent to

str.IsEmpty() ? strNull : (LPCTSTR) str

since CString is convertible to LPCTSTR but not the other way around.

Inlining the cast,

    str.IsEmpty() ? (LPCTSTR) NULL : str

should give the same effect as the second.

Thermobarometer answered 7/9, 2016 at 14:27 Comment(2)
And I'm still confused how the CString c'tor is resolved in the expression CString(NULL). There are several c'tors that take pointer arguments. How does the compiler pick one (and which one is it)?Gruesome
I get it now: All c'tors taking a single pointer argument are explicit, except for the one taking a const XCHAR*.Gruesome
A
1

At first glance, I imagine that

Func1((str.IsEmpty() ? (LPCTSTR)NULL : str));

would also work, and if it does, you probably have a type casting problem which was fixed by the

LPCTSTR strNull = NULL;

assignment because it will associate the type LPCTSTR with the value of null when strNull is called later.

Alanealanine answered 7/9, 2016 at 14:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.