blob: ed542a04fc99c14924b6acbe8bf3f620aa01106b [file] [log] [blame]
// { 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;
}