none
Can we use return L""; in the std::wstring function in C++? RRS feed

  • Question

  • Hello All,


    In my project I found the function with std::wstring return type. And in the function, if the RegGetValue function's return value is not equal to ERROR_SUCCESS then writing the statement return L"";

    Is it the correct way to use return L""; or is there any other way can we use?

    And also what is the purpose of using std::wstring as the return type from this function?

    Below is the code snippet:

    std::wstring EmrUtils::GetPIDFromRegistry()
    {
    WCHAR szPID[MAX_PATH] = { 0 };
    DWORD dwType = REG_SZ;
    DWORD dwMaxSize = sizeof(szPID) / sizeof(WCHAR);

    // Registry read
    DWORD dwRet = RegGetValue(HKEY_LOCAL_MACHINE, REGKEY_INSTALL_PARAMS, REG_VALUE_PID, 0, &dwType, (LPBYTE)&szPID, &dwMaxSize);

    if (ERROR_SUCCESS != dwRet)
    {
    return L"";
    }

    return szPID;
    }


    Friday, October 18, 2019 10:02 AM

Answers

  • The function retrieves a C style wide string from the registry.  Inside the function this is stored in the local variable szPID. Using std::wstring as the return type is a convenient way to copy the string out of the function when it returns.  The function cannot return a pointer since after returning szPID will be out of scope and the pointer will be invalid. The other way to return the string that is often seen in Windows API functions is to pass the function a buffer to use to hold the results and the length of the buffer.

    If the function fails, it uses L"" to return an empty wide string value.
    • Marked as answer by David student Saturday, October 19, 2019 7:50 AM
    Friday, October 18, 2019 10:19 AM
  • return L""; would work fine. But if for some reason you don't like that, a couple more ways to return an empty string:

    return std::wstring();
    return {};
    The last one requires a sufficiently modern compiler (VC17 definitely supports this; not sure about VC15).

    Igor Tandetnik

    • Marked as answer by David student Saturday, October 19, 2019 7:50 AM
    Friday, October 18, 2019 1:53 PM
  • To explain why this is fine. The std::wstring type has a constructor that takes a const wchar_t * as a parameter and not markes as explicit.

    When it gets to the return statements, both of them are not of type std::wstring. L"" is of type const wchar_t[1] and return szPID is of type wchar_t[260]. So your question about L"" also applies to the return szPID statement.

    So since they are not the same type, the compiler then searches through the constructors for std::wstring to find one which could create the object based on the parameter given, the closest one it finds is the std::wstring::wstring(const wchar_t *) constructor.

    This ticks all the boxes.

    1) It is the closest that the compiler can find even though it still needs some conversions.

    2) type[] degrades to type *.

    3) The compiler is allowed to add extra constraints, so adding a const to wchar_t * is fine.

    So return L""; is rewritten to return std::wstring(L""); and return szPID; is rewritten to return std::wstring(szPID);.

    This is a nice little way to to do this without having to go through the annoying copying of the array.


    This is a signature. Any samples given are not meant to have error checking or show best practices. They are meant to just illustrate a point. I may also give inefficient code or introduce some problems to discourage copy/paste coding. This is because the major point of my posts is to aid in the learning process.

    • Marked as answer by David student Saturday, October 19, 2019 7:50 AM
    Friday, October 18, 2019 2:43 PM

All replies

  • Hello,

    returning L"" is correct for a wstring return type.

    RegGetValue will either be RegGetValueW if compilation is in UNICODE or RegGetValueA if it's not UNICODE.

    Accordingly, the Project Setting to use the function EmrUtils::GetPIDFromRegistry must be UNICODE. If not, then szPID will be wrong after the call to RegGetValue. It must be RegGetValueW explicitly, so the source code is wrong.

    Regards, Guido

    Friday, October 18, 2019 10:14 AM
  • The function retrieves a C style wide string from the registry.  Inside the function this is stored in the local variable szPID. Using std::wstring as the return type is a convenient way to copy the string out of the function when it returns.  The function cannot return a pointer since after returning szPID will be out of scope and the pointer will be invalid. The other way to return the string that is often seen in Windows API functions is to pass the function a buffer to use to hold the results and the length of the buffer.

    If the function fails, it uses L"" to return an empty wide string value.
    • Marked as answer by David student Saturday, October 19, 2019 7:50 AM
    Friday, October 18, 2019 10:19 AM
  • Below is the code snippet:

    std::wstring EmrUtils::GetPIDFromRegistry()
    {
    WCHAR szPID[MAX_PATH] = { 0 };
    DWORD dwType = REG_SZ;
    DWORD dwMaxSize = sizeof(szPID) / sizeof(WCHAR);

    // Registry read
    DWORD dwRet = RegGetValue(HKEY_LOCAL_MACHINE, REGKEY_INSTALL_PARAMS, REG_VALUE_PID, 0, &dwType, (LPBYTE)&szPID, &dwMaxSize);

    if (ERROR_SUCCESS != dwRet)
    {
    return L"";
    }

    return szPID;
    }


    This code also has errors - you must pass a value other than 0  for the dwFlags parameter and the pcbData parameter should point to a DWORD that contains the size of the buffer in bytes, not characters.

    Friday, October 18, 2019 10:38 AM
  • return L""; would work fine. But if for some reason you don't like that, a couple more ways to return an empty string:

    return std::wstring();
    return {};
    The last one requires a sufficiently modern compiler (VC17 definitely supports this; not sure about VC15).

    Igor Tandetnik

    • Marked as answer by David student Saturday, October 19, 2019 7:50 AM
    Friday, October 18, 2019 1:53 PM
  • To explain why this is fine. The std::wstring type has a constructor that takes a const wchar_t * as a parameter and not markes as explicit.

    When it gets to the return statements, both of them are not of type std::wstring. L"" is of type const wchar_t[1] and return szPID is of type wchar_t[260]. So your question about L"" also applies to the return szPID statement.

    So since they are not the same type, the compiler then searches through the constructors for std::wstring to find one which could create the object based on the parameter given, the closest one it finds is the std::wstring::wstring(const wchar_t *) constructor.

    This ticks all the boxes.

    1) It is the closest that the compiler can find even though it still needs some conversions.

    2) type[] degrades to type *.

    3) The compiler is allowed to add extra constraints, so adding a const to wchar_t * is fine.

    So return L""; is rewritten to return std::wstring(L""); and return szPID; is rewritten to return std::wstring(szPID);.

    This is a nice little way to to do this without having to go through the annoying copying of the array.


    This is a signature. Any samples given are not meant to have error checking or show best practices. They are meant to just illustrate a point. I may also give inefficient code or introduce some problems to discourage copy/paste coding. This is because the major point of my posts is to aid in the learning process.

    • Marked as answer by David student Saturday, October 19, 2019 7:50 AM
    Friday, October 18, 2019 2:43 PM