1 #pragma once
2 
3 #include <filesystem>
4 #include <utility>
5 
6 namespace util
7 {
8 
9 namespace fs = std::filesystem;
10 
11 /**
12  * @class TemporaryFile
13  *
14  * A temporary file in the file system.
15  *
16  * The temporary file is created by the constructor.  The absolute path to the
17  * file can be obtained using getPath().
18  *
19  * The temporary file can be deleted by calling remove().  Otherwise the file
20  * will be deleted by the destructor.
21  *
22  * TemporaryFile objects cannot be copied, but they can be moved.  This enables
23  * them to be stored in containers like std::vector.
24  */
25 class TemporaryFile
26 {
27   public:
28     // Specify which compiler-generated methods we want
29     TemporaryFile(const TemporaryFile&) = delete;
30     TemporaryFile& operator=(const TemporaryFile&) = delete;
31 
32     /**
33      * Constructor.
34      *
35      * Creates a temporary file in the temporary directory (normally /tmp).
36      *
37      * Throws an exception if the file cannot be created.
38      */
39     TemporaryFile();
40 
41     /**
42      * Move constructor.
43      *
44      * Transfers ownership of a temporary file.
45      *
46      * @param file TemporaryFile object being moved
47      */
TemporaryFile(TemporaryFile && file)48     TemporaryFile(TemporaryFile&& file) : path{std::move(file.path)}
49     {
50         // Clear path in other object; after move path is in unspecified state
51         file.path.clear();
52     }
53 
54     /**
55      * Move assignment operator.
56      *
57      * Deletes the temporary file owned by this object.  Then transfers
58      * ownership of the temporary file owned by the other object.
59      *
60      * Throws an exception if an error occurs during the deletion.
61      *
62      * @param file TemporaryFile object being moved
63      */
64     TemporaryFile& operator=(TemporaryFile&& file);
65 
66     /**
67      * Destructor.
68      *
69      * Deletes the temporary file if necessary.
70      */
~TemporaryFile()71     ~TemporaryFile()
72     {
73         try
74         {
75             remove();
76         }
77         catch (...)
78         {
79             // Destructors should not throw exceptions
80         }
81     }
82 
83     /**
84      * Deletes the temporary file.
85      *
86      * Does nothing if the file has already been deleted.
87      *
88      * Throws an exception if an error occurs during the deletion.
89      */
90     void remove();
91 
92     /**
93      * Returns the absolute path to the temporary file.
94      *
95      * Returns an empty path if the file has been deleted.
96      *
97      * @return temporary file path
98      */
getPath() const99     const fs::path& getPath() const
100     {
101         return path;
102     }
103 
104   private:
105     /**
106      * Absolute path to the temporary file.
107      *
108      * Empty when file has been deleted.
109      */
110     fs::path path{};
111 };
112 
113 } // namespace util
114