C++20のコンセプト関係のメモです。
- std::destructibleはnoexcept(true)なデストラクタを持つクラスを含まない
- std::constructible_fromコンセプトはnoexcept(true)なデストラクタを持つクラスを含まない
- ある型が特定の型の引数から構築可能か調べる
- std::ranges::sized_rangeを区切り文字列指定で標準出力へ出力する
std::destructible
はnoexcept(true)
なデストラクタを持つクラスを含まない
std::destructible
はnoexcept(false)
なデストラクタを持つクラスを意味します。デストラクタはnoexcept(...)
を省略すると例外的にnoexcept(true)
が指定される特殊な関数なので通常は問題になりませんが、明示的にnoexcept(true)
が指定された場合はデストラクト可能でもstd::destructible
はfalse
となります。これはstd::destructive
が次の通り定義されることに由来します(参考:cppreference)。
template < class T > concept destructible = std::is_nothrow_destructible_v<T>;
次のコードではclass_nothrow_destruct
クラスはnoexcept(true)
なデストラクタを持ち、class_throw_destruct
クラスはnoexcept(false)
なデストラクタを持ちます。std::destructive
は前者でtrue
、後者でfalse
となります。
#include <concepts> #include <iostream> struct class_nothrow_destruct { ~class_nothrow_destruct() /*noexcept(true)*/ { } }; struct class_throw_destruct { ~class_throw_destruct() noexcept(false) { } }; int main() { std::wcout.setf(std::ios_base::boolalpha); // std::destructible = std::is_nothrow_destructible_v std::wcout << std::destructible<class_nothrow_destruct> << std::endl; // true std::wcout << std::destructible<class_throw_destruct> << std::endl; // false // std::is_destructible_v std::wcout << std::is_destructible_v<class_nothrow_destruct> << std::endl; // true std::wcout << std::is_destructible_v<class_throw_destruct> << std::endl; // true return 0; }
std::constructible_from
コンセプトはnoexcept(true)
なデストラクタを持つクラスを含まない
std::constructible_from
コンセプトはクラスがある型の引数から構築可能であることを示しますが、クラスがnoexcept(true)
なデストラクタを持つ場合はfalse
となります。これはstd::constructible_from
の定義が以下の通りであり、std::destructible<T>
がnoexcept(false)
なデストラクタしかtrue
を返さないことに由来します(参考:cppreference)。
template < class T, class... Args > concept constructible_from = std::destructible<T> && std::is_constructible_v<T, Args...>;
ある型が特定の型の引数から構築可能か調べる
std::constructible_from
を使えばある型が特定の型の引数から構築可能か調べることができます。ただし、noexcept(true)
なデストラクタを持つクラスを含まないことに注意してください。
#include <concepts> #include <iostream> #include <string_view> int main() { std::wcout.setf(std::ios_base::boolalpha); // std::wstring_viewがstd::wstring、wchar_t[]等からそれぞれ構築可能か。 std::wcout << std::constructible_from<std::wstring_view, std::wstring> << std::endl // true << std::constructible_from<std::wstring_view, wchar_t[]> << std::endl // true << std::constructible_from<std::wstring_view, wchar_t*> << std::endl // true << std::constructible_from<std::wstring_view, std::string> << std::endl // false << std::constructible_from<std::wstring_view, int> << std::endl; // false return 0; }
std::ranges::sized_range
を区切り文字列指定で標準出力へ出力する
#include <iostream> #include <ranges> #include <vector> template <std::ranges::sized_range T> void print(T r, std::wstring_view sep = L", ") { std::ranges::subrange sr(r.begin(), std::prev(r.end(), 1)); for (const auto& elem : sr) { std::wcout << elem << sep; } std::wcout << *std::next(r.begin(), r.size() - 1) << std::endl; } int main() { print(std::vector{ 0, 1, 2, 3, 4 }); }