-1

I'm trying to write a program capable of renaming files, but I'm encountering a weird issue. When I write this:

string oldname, newname;
rename(oldname, newname);

Everything works fine. The file is renamed and there are no problems. But then when I go ahead and try this:

int result;
result = rename(oldname, newname);
if(result)
//stuff
else
//other stuff

The "=" gets a fresh new red underline and I get an error "a value of type "void" cannot be assigned to an entity of type "int"". I also tried

if(rename(oldname, newname))
//stuff

Then I just get "expression must have bool type (or be convertible to bool)"

Microsoft's documentation says that the rename function returns 0 if successful and nonzero if not successful. After a lot of googling I found countless examples of code that use the second or third snippet without issue, and none of it has helped me understand what might be different in my situation. The language standard is C++17. I can't think of any other relevant details, but just in case, here is a snippet of the actual code with all the "includes":

#include <windows.h>
#include <stdlib.h>
#include <tchar.h>
#include <vector>
#include <string>
#include <filesystem>
#include <fstream>
#include <time.h>
#include <iostream>
#include <codecvt>
#include <locale>
#include <sstream>
#include <windowsx.h>
#include <Shlobj.h>

using namespace std;
using namespace std::filesystem;

tmp_wstr = oldname + L"\n\nwill be renamed to:\n\n" + newname + L"\n\nWould you like to proceed?";
                        msgboxID = MessageBox(NULL, tmp_wstr.c_str(), L"Renaming...", MB_YESNO | MB_SYSTEMMODAL);
                        switch (msgboxID)
                        {
                        case IDYES:
                            result = rename(oldname, newname);
                            if (result)
                            {
                                error = true;
                                msgboxID = MessageBox(NULL, L"Unable to rename", NULL, MB_OK | MB_SYSTEMMODAL);
                            }
                            else
                                error = false;
                            break;
                        case IDNO:
                            error = true;
                            break;
                        }

Here oldname and newname are wstring instead of string, but I have tried using string and the error persists.

1 Answers1

4

You are expecting to call the C standard library function rename() with signature:

int rename(const char*, const char*);

But that function would not be a viable overload for rename(oldname, newname) if oldname and newname are of type std::(w)string, since std::(w)string is not implicitly convertible to const char*.

So, you must be calling a different function named rename(). Since you used:

using namespace std::filesystem;

you are, in fact, calling the following overload of the C++ standard library function std::filesystem::rename() with signature:

void rename(const std::filesystem::path&, const std::filesystem::path&);

which is viable with your arguments, since std::filesystem::path is constructible from std::(w)string.

This function has a void return type, explaining the error messages. As explained in the link, it doesn't return a status code, but instead throws an exception if there is an error.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
user17732522
  • 53,019
  • 2
  • 56
  • 105
  • Thank you for the quick and thorough answer! – Jack Crawford Feb 07 '22 at 16:45
  • _"void return type explaining the error messages"_ seems a mistake. However there is an overloaded version with an output parameter for the error code in your link. Solid answer otherwise. – Joop Eggen Feb 07 '22 at 16:56
  • 1
    "_explaining the error messages_" which OP is getting from his code. @JoopEggen – user17732522 Feb 07 '22 at 16:57
  • My misunderstanding, thought any I/O error. – Joop Eggen Feb 07 '22 at 17:15
  • 1
    This is one of the hazards of rampant `using namespace` directives: You run into name collisions that can resolve in surprising ways. – Raymond Chen Feb 07 '22 at 17:23
  • Also the C-style `rename` is supposed to be declared in the `` header (or possibly ``) which has not been included. – Nate Eldredge Feb 07 '22 at 17:40
  • 2
    @NateEldredge C++ standard library headers are allowed to include other standard library headers and it is likely that both `` and `` will include ``, since both probably base their implementation on ``. – user17732522 Feb 07 '22 at 17:47
  • that's one of the reasons [Why "using namespace std;" is considered bad practice](https://stackoverflow.com/q/1452721/995714). You don't realized which function is actually called – phuclv Feb 08 '22 at 00:27