1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
|
// { dg-do run { target c++23 } }
// { dg-require-fileio "" }
// { dg-additional-files "thirty_years_among_the_dead_preproc.txt" }
#include <memory>
#include <cstdio>
#include <testsuite_hooks.h>
// C++23 [out.ptr.t] Class template out_ptr_t
int fopen_s(std::FILE** f, const char* name, const char* mode);
struct fclose_deleter {
void operator()(std::FILE* f) const noexcept {
std::fclose(f);
}
};
// Example 1 from [out.ptr.t]
void
test_example_1()
{
constexpr const char* file_name = "thirty_years_among_the_dead_preproc.txt";
std::unique_ptr<std::FILE, fclose_deleter> file_ptr;
int err = fopen_s(std::out_ptr<std::FILE*>(file_ptr), file_name, "r+b");
if (err != 0)
VERIFY(false);
// *file_ptr is valid
VERIFY(file_ptr != nullptr);
}
// Same again without explicit template argument list.
void
test_example_1_2()
{
constexpr const char* file_name = "thirty_years_among_the_dead_preproc.txt";
std::unique_ptr<std::FILE, fclose_deleter> file_ptr;
int err = fopen_s(std::out_ptr(file_ptr), file_name, "r+b");
if (err != 0)
VERIFY(false);
// *file_ptr is valid
VERIFY(file_ptr != nullptr);
}
// And again with a deleter argument.
void
test_example_1_3()
{
constexpr const char* file_name = "thirty_years_among_the_dead_preproc.txt";
std::unique_ptr<std::FILE, fclose_deleter> file_ptr;
int err = fopen_s(std::out_ptr(file_ptr, fclose_deleter()), file_name, "r+b");
if (err != 0)
VERIFY(false);
// *file_ptr is valid
VERIFY(file_ptr != nullptr);
}
// Same again using std::shared_ptr
void
test_example_1_sp()
{
constexpr const char* file_name = "thirty_years_among_the_dead_preproc.txt";
std::shared_ptr<std::FILE> file_ptr;
int err = fopen_s(std::out_ptr<std::FILE*>(file_ptr, fclose_deleter()),
file_name, "r+b");
if (err != 0)
VERIFY(false);
// *file_ptr is valid
VERIFY(file_ptr != nullptr);
}
// And again without explicit template argument list.
void
test_example_1_sp_2()
{
constexpr const char* file_name = "thirty_years_among_the_dead_preproc.txt";
std::shared_ptr<std::FILE> file_ptr;
int err = fopen_s(std::out_ptr(file_ptr, fclose_deleter()), file_name, "r+b");
if (err != 0)
VERIFY(false);
// *file_ptr is valid
VERIFY(file_ptr != nullptr);
}
// And again using a raw pointer.
void
test_example_1_raw()
{
constexpr const char* file_name = "thirty_years_among_the_dead_preproc.txt";
std::FILE* file_ptr;
int err = fopen_s(std::out_ptr(file_ptr), file_name, "r+b");
if (err != 0)
VERIFY(false);
// *file_ptr is valid
VERIFY(file_ptr != nullptr);
std::fclose(file_ptr);
}
int main()
{
test_example_1();
test_example_1_2();
test_example_1_3();
test_example_1_sp();
test_example_1_sp_2();
test_example_1_raw();
}
#include <cerrno>
int fopen_s(std::FILE** f, const char* name, const char* mode)
{
if ((*f = std::fopen(name, mode)))
return 0;
return errno;
}
|