Compiler Error C2664 - visual-c++

Having trouble with this compiler error, I can't figure out what its moaning about. If anyone could help I will be very grateful. Here is the error:
Error 1 error C2664: 'CPropertyPage::CPropertyPage(UINT,UINT,DWORD)' : cannot convert parameter 2 from 'CWnd *' to 'UINT' c:\users\bnason.prolec\documents\visual studio 2005\projects\autorepair1\autorepair1\customerinformationdlg.cpp 20
and here is the code that seems to be causing it:
CRepairOrderSheet::CRepairOrderSheet(LPCTSTR pszCaption, CWnd* pParentWnd, UINT iSelectPage)
:CPropertySheet(pszCaption, pParentWnd, iSelectPage)
{
this->AddPage(&dlgCustomerInformation);
this->AddPage(&dlgJobsAndParts);
this->AddPage(&dlgRepairSummary);
}

The CPropertyPage constructor takes three parameters: UINT, UINT, and DWORD. It's not clear whether your CRepairOrderSheet derives from CPropertyPage or CPropertySheet (information not provided in question), but the compiler thinks you're trying to construct a CPropertyPage. You are passing it LPCTSTR, CWnd* and UINT. The compiler cannot get the types to match up.

Related

Using gsl::narrow fails

I know there are similar questions and I don't know the best wording for this one.
I find it a little ironic that the reason for the code analysis warning in the first place was that it told me to use gsl::narrow into two instances:
Instance 1:
auto* pCell1 = gsl::narrow<CGridCellBase*>(lParam1);
auto* pCell2 = gsl::narrow<CGridCellBase*>(lParam2);
Compilation error:
6>D:\My Libraries\GSL-main\include\gsl\util(105,1): error C2440: 'static_cast': cannot convert from 'U' to 'T'
6> with
6> [
6> U=LPARAM
6> ]
6> and
6> [
6> T=CGridCellBase *
6> ]
6>D:\My Libraries\GSL-main\include\gsl\util(105,12): message : Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
Instance 2:
auto* pItem = gsl::narrow<NM_GRIDVIEW*>(pNotifyStruct);
Compilation error:
6>D:\My Libraries\GSL-main\include\gsl\narrow(58,1): error C2440: 'static_cast': cannot convert from 'const T' to 'U'
6> with
6> [
6> T=NM_GRIDVIEW *
6> ]
6> and
6> [
6> U=NMHDR *
6> ]
6>D:\My Libraries\GSL-main\include\gsl\narrow(58,9): message : Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
Those messages are telling me to do the reverse:
Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
Going around in circles! Given the situation then, am I to understand that the correct way forward is:
Use reinterpret_cast and...
Add appropriate prama warning to suppress the warning.
Correct?
You can't (and shouldn't try to) use anything other than a reinterpret_cast to convert between a pointer and a non-pointer, or between pointers to different (unrelated) types. The gsl::narrow function is just a 'fancy' version of static_cast: Understanding gsl::narrow implementation.
Further, when writing programs that use the WinAPI or MFC, it is virtually impossible to completely avoid casting between pointer and non-pointer types; notably, many of the message handling routines take a pointer to some data or other as their lParam argument (the LPARAM type is defined as either __int64 or int, depending on the target platform).
So, your suggestion is, IMHO, the best option:
Use reinterpret_cast and...
Add appropriate pragma warning to suppress the warning.
However, you will most likely need to add that #pragma... directive in many places in your code. So, what you can do is to create a 'helper' (or wrapper) cast of your own, which you can then use throughout your code.
For example, you can add the following to your "stdafx.h" (or "pch.h") file (or to any header that is included wherever the cast is needed):
template<typename T, typename U> static T inline pointer_cast(U src) noexcept
{
static_assert(sizeof(T) >= sizeof(U), "Invalid pointer cast"); // Check sizes!
__pragma(warning(suppress:26490)) // Note: no semicolon after this expression!
return reinterpret_cast<T>(src);
}
You can then use that pointer_cast and avoid having to add the pragma each time. Here's a typical example, using a potential message handler for the WM_NOTIFY message in a custom dialog box class:
BOOL MyDialog::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT *pResult)
{
NMHDR* pHdr = pointer_cast<NMHDR*>(lParam);
switch (pHdr->code) {
//... remaining code ...
Note: on the use of the __pragma() directive (rather than #pragma), see here.

Misaligned pointer use with std::shared_ptr<NSDate> dereference

I am working in a legacy codebase with a large amount of Objective-C++ written using manual retain/release. Memory is managed using lots of C++ std::shared_ptr<NSMyCoolObjectiveCPointer>, with a suitable deleter passed in on construction that calls release on the contained object. This seems to work great; however, when enabling UBSan, it complains about misaligned pointers, usually when dereferencing the shared_ptrs to do some work.
I've searched for clues and/or solutions, but it's difficult to find technical discussion of the ins and outs of Objective-C object pointers, and even more difficult to find any discussion about Objective-C++, so here I am.
Here is a full Objective-C++ program that demonstrates my problem. When I run this on my Macbook with UBSan, I get a misaligned pointer issue in shared_ptr::operator*:
#import <Foundation/Foundation.h>
#import <memory>
class DateImpl {
public:
DateImpl(NSDate* date) : _date{[date retain], [](NSDate* date) { [date release]; }} {}
NSString* description() const { return [&*_date description]; }
private:
std::shared_ptr<NSDate> _date;
};
int main(int argc, const char * argv[]) {
#autoreleasepool {
DateImpl date{[NSDate distantPast]};
NSLog(#"%#", date.description());
return 0;
}
}
I get this in the call to DateImpl::description:
runtime error: reference binding to misaligned address 0xe2b7fda734fc266f for type 'std::__1::shared_ptr<NSDate>::element_type' (aka 'NSDate'), which requires 8 byte alignment
0xe2b7fda734fc266f: note: pointer points here
<memory cannot be printed>
I suspect that there is something awry with the usage of &* to "cast" the shared_ptr<NSDate> to an NSDate*. I think I could probably work around this issue by using .get() on the shared_ptr instead, but I am genuinely curious about what is going on. Thanks for any feedback or hints!
There were some red herrings here: shared_ptr, manual retain/release, etc. But I ended up discovering that even this very simple code (with ARC enabled) causes the ubsan hit:
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
#autoreleasepool {
NSDate& d = *[NSDate distantPast];
NSLog(#"%#", &d);
}
return 0;
}
It seems to simply be an issue with [NSDate distantPast] (and, incidentally, [NSDate distantFuture], but not, for instance, [NSDate date]). I conclude that these must be singleton objects allocated sketchily/misaligned-ly somewhere in the depths of Foundation, and when you dereference them it causes a misaligned pointer read.
(Note it does not happen when the code is simply NSLog(#"%#", &*[NSDate distantPast]). I assume this is because the compiler simply collapses &* on a raw pointer into a no-op. It doesn't for the shared_ptr case in the original question because shared_ptr overloads operator*. Given this, I believe there is no easy way to make this happen in pure Objective-C, since you can't separate the & operation from the * operation, like you can when C++ references are involved [by storing the temporary result of * in an NSDate&].)
You are not supposed to ever use a "bare" NSDate type. Objective-C objects should always be used with a pointer-to-object type (e.g. NSDate *), and you are never supposed to get the "type behind the pointer".
In particular, on 64-bit platforms, Objective-C object pointers can sometimes not be valid pointers, but rather be "tagged pointers" which store the "value" of the object in certain bits of the pointer, rather than as an actual allocated object. You must always let the Objective-C runtime machinery deal with Objective-C object pointers. Dereferencing it as a regular C/C++ pointer can lead to undefined behavior.

redefinition of default parameter error without redefining

I am getting a strange set of error in my Visual Studio 2010 compiler.
I am getting the errors of
error C2572: redefinition of default parameter
error C2011: 'class' type redefinition
I have checked thoroughly and I know very well that in the function definition, I have not given the default parameter values and I have given default parameter value only in function prototype in the header file.
Also, I am very much sure that no two class has been given the same class name.
Please can anybody tell me what could be the other reasons for getting these set of errors?
I have not got the exact reason why it was happening, but I have overcome it by using some simple techniques.
I used function overloading concept to avoid default parameter list. It will cause in duplication of code, but it has proved to be very effective.
So something like this
void myFunction( int, char * = '\0', char * = '\0' );
would become something like this
void myFunction( int );
void myFunction( int, char * );
void myFunction( int, char *, char * );
In this example, code is getting duplicated two times but it seems to be only work around solution.
Next, for the strange class type redefinition error, I was instantiating the class variable in many files. So, I removed that feature of instantiation everywhere and went with global variable something like this.
File named as myHeader.h
#include "myFile.h"
myClass myObj;
And in all the other files
#include "myHeader.h"
myObj.function1( );
myObj.function2( );

c2664 in Visual Studio 2012 when using make_pair

I dig up an old project and wanted to compile it, but received several errors, a few of those being a c2664:
error C2664: 'std::make_pair' : cannot convert parameter 1 from 'CUser *' to 'CUser *&&'
error C2664: 'std::make_pair' : cannot convert parameter 1 from 'unsigned long' to ' unsigned long &&'
The relevant code parts are:
//typedef for the userdata map
typedef std::map<unsigned long, std::pair<CUser*,userstatus*>> UserDataMapType;
//...
Inc::incret CUserManager::AddUser(unsigned long ID, CUser* pUser, userstatus* pUserStatus)
{
//...
std::pair<UserDataMapType::iterator, bool> ret = m_mapUserData.insert(std::make_pair<unsigned long, std::pair<CUser*, userstatus*>>(ID, std::make_pair<CUser*, userstatus*>(pUser, pUserStatus)));
//...
}
I tried to make the function parameters const, but that did not help.
It did compile just fine in VS2010.
Please help me find what causes this and how to solve it.
make_pair() has been changed in VS2012 to support a new C++11 feature called move semantics and I suspect that explicitly specifying the types for make_pair() is getting in the way.
Remember that make_pair() does not need any template parameters to be explicitly specified. It deduces them from the type of each argument.
Try removing the explicit template arguments from both calls to make_pair() like so...
std::pair<UserDataMapType::iterator, bool> ret = m_mapUserData.insert(std::make_pair(ID, std::make_pair(pUser, pUserStatus)));
Explicitly providing them like this would have worked fine pre-VS2012 because of a new C++11 feature added called move semantics. You'll want to read up on that subject later since you have a shiny new compiler that supports it.

The explicit keyword in MS Visual Studio 4.1

I am implementing a smart pointer class using generics and I wanted to force users of this class to properly construct the smart pointer using syntax such as
MyReference<TestCls>(mytest3))
or
MyReference<TestCls> mytest4(new TestCls());
so I have used the explicit keyword on the CTOR, to prevent this:
MyReference aRef = NULL;
However due to unfortunate circumstances beyond my control, I am working on code that is compiled using the ancient MSVC++ 4.1 compiler. I get the following errors when I include the explicit keyword:
MyReference.h(49) : error C2501: 'explicit' : missing decl-specifiers
MyReference.h(51) : error C2143: syntax error : missing ';' before ''
MyReference.h(52) : error C2238: unexpected token(s) preceding ':'
MyReference.h(52) : error C2059: syntax error : 'int constant'
When I add a #define explicit those errors disappear.
This was a hack on my part, just to get the compiler to ignore the keyword. I'm guessing that this means that explicit is not supported by yon olde compiler.
Can someone confirm this and is there anyone out there with knowledge of a workaround solution for this?
Merci Beaucoups,
Dennis.
This site has a workaround for this, namely:
Unfortunately, older compilers may not
support the use of "explicit", which
could be a headache. If you're stuck
working with an out-of-date compiler
and can't get one that has better
support for the C++ standard, your
best solution may be to take advantage
of the fact that only a single
implicit conversion will take place
for a given value. You can exploit
this by using an intermediate class
that implicitly creates an object of
each type, and then have your main
class implicitly create objects from
that class:
class proxy
{
public:
proxy(int x) : x(x) {} ;
getValue() { return x; }
private:
int x;
};
class String
{
// this will be equivalent of explicit
String(proxy x) { /* create a string using x.getValue(); */ }
}

Resources