Using gsl::narrow fails - visual-c++

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.

Related

What is equivalent mmap in C++ for linux?

What is equivalent mmap into C++?
I have code like below
LCDdata = mmap(NULL, iFrameBufferSize, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, fb_fd, 0);
Where LCDdata is unsigned char type pointer, iFrameBufferSize is int type and fb_fd is static int type.
When I compile it by use of arm g++ tool chain it give me error as below
error: invalid conversion from 'void*' to 'unsigned char*' [-fpermissive]
So how can I use any equivalent type function instead of mmap?
Which header file I should include? And how this new line's syntax will become?
The C++ equivalent is auto LCDdata = static_cast<unsigned char*>(mmap(...
In C++ we prefer to define out variables only when we initialize them, and because of that we often don't need to specify the type anymore. Here, we don't need to repeat unsigned char*.
C allows void* to be assigned to pointers of any type without a cast. C++ does not. C programmers have complained about this for ages (malloc being the most common complaint), but it's not likely to change.
The solution is to add the cast. If the source needs to be compilable as C, use a C-style cast:
LCDdata = (unsigned char*)mmap(...);
Otherwise use a C++ cast
LCDdata = static_cast<unsigned char*>(mmap(...));
If you want to do something more drastic, you could look into Boost Interprocess. That would give you RAII.

Visual C++ run times error

All case run in Visual C++ 2005 environment
Function definition:
char *PQgetvalue(const PGresult *res, int tup_num, int field_num);
Case 1.
CString dd;
dd=(LPCTSTR) PQgetvalue(res,i,0);
when above is compiled with NO ERROR but dd has store garbage data like: 〱〰71〱1 몭몭몭몭몭몭ꮫꮫꮫꮫ
Case 2.
CString dd;
dd= PQgetvalue(res,i,0);
No Compilation error and provide correct output.
Question: How to convert Char* to CString
Case 3.
CString dd;
dd= PQgetvalue(res,i,0);
CString dd = PQgetvalue(res,i,0);
There is NO Difference between above code. But second case generate compilation error like:
error C2440: 'initializing' :
cannot convert from 'char *' to 'ATL::CStringT<BaseType,StringTraits>'
Please clarify anyone
For the first case. I guess you compile your project with Unicode character set (to verify open project settings dialog "Configuration properties" - "General" - "Character set"). Thus converting char* to const wchar_t* would gives you garbage. I.e. TCHAR is wchar_t when you compile with Unicode.
On the C2440. Please clarify whether code in Case 3 is correct (i.e. you supply all 3 lines to compiler as provided here.). Also I'd suggest you to search MSDN on this error.

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.

Compiler Error C2664

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.

how visual studio tell c++ and c?

As the title says,does the visual studio distinguish these two files by their suffix?.c or .cpp?
I also have another question.At first,I stated the program like this:
int main(int argc, char **argv)
{
LARGE_INTEGER TimeStart;
LARGE_INTEGER TimeEnd;
QueryPerformanceCounter(&TimeStart);
static double Freq;
static int getfreq;
double mu,om;
double *v;
int it,i,j;
....
}
but it brings out many problems:
1>sor2d.c(23): error C2143: syntax error : missing ';' before 'type'
1>sor2d.c(24): error C2143: syntax error : missing ';' before 'type'
1>sor2d.c(25): error C2143: syntax error : missing ';' before 'type'
1>sor2d.c(26): error C2143: syntax error : missing ';' before 'type'
23 ling points to "static double Freq;"
but if I put "QueryPerformanceCounter(&TimeStart);" after the data allocation,the compiler can succeed.Could someone tell me why this happened,was is just because of my carelessness of omitting something or ignorance...?
In C, all variables must be declared before calling any methods.
Visual Studio will, by default, compile .C files as C. You can override this.
In C89, you must declare all of your variables at the top of the code block. You may also initialize them to compile-time constants (literals, macros that expand to literals, the values of variables that have already been initialized, and any operations on the above that can be performed at compile time). You cannot intersperse other types of statements (like function calls) within these declarations.
This limitation was removed in C99 (which is not supported by Visual C++) and C++.

Resources