422 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++14, c++1710 11// template<class From, class To>12// concept convertible_to;13 14#include <concepts>15#include <type_traits>16 17namespace {18enum ClassicEnum { a, b };19enum class ScopedEnum { x, y };20struct Empty {};21using nullptr_t = decltype(nullptr);22 23template <class T, class U>24void CheckConvertibleTo() {25 static_assert(std::convertible_to<T, U>);26 static_assert(std::convertible_to<const T, U>);27 static_assert(std::convertible_to<T, const U>);28 static_assert(std::convertible_to<const T, const U>);29}30 31template <class T, class U>32void CheckNotConvertibleTo() {33 static_assert(!std::convertible_to<T, U>);34 static_assert(!std::convertible_to<const T, U>);35 static_assert(!std::convertible_to<T, const U>);36 static_assert(!std::convertible_to<const T, const U>);37}38 39template <class T, class U>40void CheckIsConvertibleButNotConvertibleTo() {41 // Sanity check T is either implicitly xor explicitly convertible to U.42 static_assert(std::is_convertible_v<T, U>);43 static_assert(std::is_convertible_v<const T, U>);44 static_assert(std::is_convertible_v<T, const U>);45 static_assert(std::is_convertible_v<const T, const U>);46 CheckNotConvertibleTo<T, U>();47}48 49// Tests that should objectively return false (except for bool and nullptr_t)50template <class T>51constexpr void CommonlyNotConvertibleTo() {52 CheckNotConvertibleTo<T, void>();53 CheckNotConvertibleTo<T, nullptr_t>();54 CheckNotConvertibleTo<T, T*>();55 CheckNotConvertibleTo<T, T Empty::*>();56 CheckNotConvertibleTo<T, T (Empty::*)()>();57 CheckNotConvertibleTo<T, T[sizeof(T)]>();58 CheckNotConvertibleTo<T, T (*)()>();59 CheckNotConvertibleTo<T, T (&)()>();60 CheckNotConvertibleTo<T, T(&&)()>();61}62 63template <std::same_as<bool> >64constexpr void CommonlyNotConvertibleTo() {65 CheckNotConvertibleTo<bool, void>();66 CheckNotConvertibleTo<bool, nullptr_t>();67 CheckConvertibleTo<bool Empty::*, bool>();68 CheckConvertibleTo<bool (Empty::*)(), bool>();69 CheckConvertibleTo<bool[2], bool>();70 CheckConvertibleTo<bool (*)(), bool>();71 CheckConvertibleTo<bool (&)(), bool>();72 CheckConvertibleTo<bool(&&)(), bool>();73}74 75template <std::same_as<nullptr_t> >76constexpr void CommonlyNotConvertibleTo() {77 CheckNotConvertibleTo<nullptr_t, void>();78 CheckConvertibleTo<nullptr_t, nullptr_t>();79 CheckConvertibleTo<nullptr_t, void*>();80 CheckConvertibleTo<nullptr_t, int Empty::*>();81 CheckConvertibleTo<nullptr_t, void (Empty::*)()>();82 CheckNotConvertibleTo<nullptr_t, int[2]>();83 CheckConvertibleTo<nullptr_t, void (*)()>();84 CheckNotConvertibleTo<nullptr_t, void (&)()>();85 CheckNotConvertibleTo<nullptr_t, void(&&)()>();86}87} // namespace88 89using Function = void();90using NoexceptFunction = void() noexcept;91using ConstFunction = void() const;92using Array = char[1];93 94struct StringType {95 StringType(const char*) {}96};97 98class NonCopyable {99 NonCopyable(NonCopyable&);100};101 102template <typename T>103class CannotInstantiate {104 enum { X = T::ThisExpressionWillBlowUp };105};106 107struct abstract {108 virtual int f() = 0;109};110 111struct ExplicitlyConvertible;112struct ImplicitlyConvertible;113 114struct ExplicitlyConstructible {115 explicit ExplicitlyConstructible(int);116 explicit ExplicitlyConstructible(ExplicitlyConvertible);117 explicit ExplicitlyConstructible(ImplicitlyConvertible) = delete;118};119 120struct ExplicitlyConvertible {121 explicit operator ExplicitlyConstructible() const {122 return ExplicitlyConstructible(0);123 }124};125 126struct ImplicitlyConstructible;127 128struct ImplicitlyConvertible {129 operator ExplicitlyConstructible() const;130 operator ImplicitlyConstructible() const = delete;131};132 133struct ImplicitlyConstructible {134 ImplicitlyConstructible(ImplicitlyConvertible);135};136 137int main(int, char**) {138 // void139 CheckConvertibleTo<void, void>();140 CheckNotConvertibleTo<void, Function>();141 CheckNotConvertibleTo<void, Function&>();142 CheckNotConvertibleTo<void, Function*>();143 CheckNotConvertibleTo<void, NoexceptFunction>();144 CheckNotConvertibleTo<void, NoexceptFunction&>();145 CheckNotConvertibleTo<void, NoexceptFunction*>();146 CheckNotConvertibleTo<void, Array>();147 CheckNotConvertibleTo<void, Array&>();148 CheckNotConvertibleTo<void, char>();149 CheckNotConvertibleTo<void, char&>();150 CheckNotConvertibleTo<void, char*>();151 CheckNotConvertibleTo<char, void>();152 153 // Function154 CheckNotConvertibleTo<Function, void>();155 CheckNotConvertibleTo<Function, Function>();156 CheckNotConvertibleTo<Function, NoexceptFunction>();157 CheckNotConvertibleTo<Function, NoexceptFunction&>();158 CheckNotConvertibleTo<Function, NoexceptFunction*>();159 CheckNotConvertibleTo<Function, NoexceptFunction* const>();160 CheckConvertibleTo<Function, Function&>();161 CheckConvertibleTo<Function, Function*>();162 CheckConvertibleTo<Function, Function* const>();163 164 static_assert(std::convertible_to<Function, Function&&>);165 static_assert(!std::convertible_to<Function, NoexceptFunction&&>);166 167 CheckNotConvertibleTo<Function, Array>();168 CheckNotConvertibleTo<Function, Array&>();169 CheckNotConvertibleTo<Function, char>();170 CheckNotConvertibleTo<Function, char&>();171 CheckNotConvertibleTo<Function, char*>();172 173 // Function&174 CheckNotConvertibleTo<Function&, void>();175 CheckNotConvertibleTo<Function&, Function>();176 CheckConvertibleTo<Function&, Function&>();177 178 CheckConvertibleTo<Function&, Function*>();179 CheckNotConvertibleTo<Function&, Array>();180 CheckNotConvertibleTo<Function&, Array&>();181 CheckNotConvertibleTo<Function&, char>();182 CheckNotConvertibleTo<Function&, char&>();183 CheckNotConvertibleTo<Function&, char*>();184 185 // Function*186 CheckNotConvertibleTo<Function*, void>();187 CheckNotConvertibleTo<Function*, Function>();188 CheckNotConvertibleTo<Function*, Function&>();189 CheckConvertibleTo<Function*, Function*>();190 191 CheckNotConvertibleTo<Function*, Array>();192 CheckNotConvertibleTo<Function*, Array&>();193 CheckNotConvertibleTo<Function*, char>();194 CheckNotConvertibleTo<Function*, char&>();195 CheckNotConvertibleTo<Function*, char*>();196 197 // Non-referencable function type198 static_assert(!std::convertible_to<ConstFunction, Function>);199 static_assert(!std::convertible_to<ConstFunction, Function*>);200 static_assert(!std::convertible_to<ConstFunction, Function&>);201 static_assert(!std::convertible_to<ConstFunction, Function&&>);202 static_assert(!std::convertible_to<Function*, ConstFunction>);203 static_assert(!std::convertible_to<Function&, ConstFunction>);204 static_assert(!std::convertible_to<ConstFunction, ConstFunction>);205 static_assert(!std::convertible_to<ConstFunction, void>);206 207 // NoexceptFunction208 CheckNotConvertibleTo<NoexceptFunction, void>();209 CheckNotConvertibleTo<NoexceptFunction, Function>();210 CheckNotConvertibleTo<NoexceptFunction, NoexceptFunction>();211 CheckConvertibleTo<NoexceptFunction, NoexceptFunction&>();212 CheckConvertibleTo<NoexceptFunction, NoexceptFunction*>();213 CheckConvertibleTo<NoexceptFunction, NoexceptFunction* const>();214 CheckConvertibleTo<NoexceptFunction, Function&>();215 CheckConvertibleTo<NoexceptFunction, Function*>();216 CheckConvertibleTo<NoexceptFunction, Function* const>();217 218 static_assert(std::convertible_to<NoexceptFunction, Function&&>);219 static_assert(std::convertible_to<NoexceptFunction, NoexceptFunction&&>);220 221 CheckNotConvertibleTo<NoexceptFunction, Array>();222 CheckNotConvertibleTo<NoexceptFunction, Array&>();223 CheckNotConvertibleTo<NoexceptFunction, char>();224 CheckNotConvertibleTo<NoexceptFunction, char&>();225 CheckNotConvertibleTo<NoexceptFunction, char*>();226 227 // NoexceptFunction&228 CheckNotConvertibleTo<NoexceptFunction&, void>();229 CheckNotConvertibleTo<NoexceptFunction&, Function>();230 CheckNotConvertibleTo<NoexceptFunction&, NoexceptFunction>();231 CheckConvertibleTo<NoexceptFunction&, Function&>();232 CheckConvertibleTo<NoexceptFunction&, NoexceptFunction&>();233 234 CheckConvertibleTo<NoexceptFunction&, Function*>();235 CheckConvertibleTo<NoexceptFunction&, NoexceptFunction*>();236 CheckNotConvertibleTo<NoexceptFunction&, Array>();237 CheckNotConvertibleTo<NoexceptFunction&, Array&>();238 CheckNotConvertibleTo<NoexceptFunction&, char>();239 CheckNotConvertibleTo<NoexceptFunction&, char&>();240 CheckNotConvertibleTo<NoexceptFunction&, char*>();241 242 // NoexceptFunction*243 CheckNotConvertibleTo<NoexceptFunction*, void>();244 CheckNotConvertibleTo<NoexceptFunction*, Function>();245 CheckNotConvertibleTo<NoexceptFunction*, Function&>();246 CheckNotConvertibleTo<NoexceptFunction*, NoexceptFunction>();247 CheckNotConvertibleTo<NoexceptFunction*, NoexceptFunction&>();248 CheckConvertibleTo<NoexceptFunction*, Function*>();249 CheckConvertibleTo<NoexceptFunction*, NoexceptFunction*>();250 251 CheckNotConvertibleTo<NoexceptFunction*, Array>();252 CheckNotConvertibleTo<NoexceptFunction*, Array&>();253 CheckNotConvertibleTo<NoexceptFunction*, char>();254 CheckNotConvertibleTo<NoexceptFunction*, char&>();255 CheckNotConvertibleTo<NoexceptFunction*, char*>();256 257 // Array258 CheckNotConvertibleTo<Array, void>();259 CheckNotConvertibleTo<Array, Function>();260 CheckNotConvertibleTo<Array, Function&>();261 CheckNotConvertibleTo<Array, Function*>();262 CheckNotConvertibleTo<Array, NoexceptFunction>();263 CheckNotConvertibleTo<Array, NoexceptFunction&>();264 CheckNotConvertibleTo<Array, NoexceptFunction*>();265 CheckNotConvertibleTo<Array, Array>();266 267 static_assert(!std::convertible_to<Array, Array&>);268 static_assert(std::convertible_to<Array, const Array&>);269 static_assert(!std::convertible_to<Array, const volatile Array&>);270 271 static_assert(!std::convertible_to<const Array, Array&>);272 static_assert(std::convertible_to<const Array, const Array&>);273 static_assert(!std::convertible_to<Array, volatile Array&>);274 static_assert(!std::convertible_to<Array, const volatile Array&>);275 276 static_assert(std::convertible_to<Array, Array&&>);277 static_assert(std::convertible_to<Array, const Array&&>);278 static_assert(std::convertible_to<Array, volatile Array&&>);279 static_assert(std::convertible_to<Array, const volatile Array&&>);280 static_assert(std::convertible_to<const Array, const Array&&>);281 static_assert(!std::convertible_to<Array&, Array&&>);282 static_assert(!std::convertible_to<Array&&, Array&>);283 284 CheckNotConvertibleTo<Array, char>();285 CheckNotConvertibleTo<Array, char&>();286 287 static_assert(std::convertible_to<Array, char*>);288 static_assert(std::convertible_to<Array, const char*>);289 static_assert(std::convertible_to<Array, char* const>);290 static_assert(std::convertible_to<Array, char* const volatile>);291 292 static_assert(!std::convertible_to<const Array, char*>);293 static_assert(std::convertible_to<const Array, const char*>);294 295 static_assert(!std::convertible_to<char[42][42], char*>);296 static_assert(!std::convertible_to<char[][1], char*>);297 298 // Array&299 CheckNotConvertibleTo<Array&, void>();300 CheckNotConvertibleTo<Array&, Function>();301 CheckNotConvertibleTo<Array&, Function&>();302 CheckNotConvertibleTo<Array&, Function*>();303 CheckNotConvertibleTo<Array&, NoexceptFunction>();304 CheckNotConvertibleTo<Array&, NoexceptFunction&>();305 CheckNotConvertibleTo<Array&, NoexceptFunction*>();306 CheckNotConvertibleTo<Array&, Array>();307 308 static_assert(std::convertible_to<Array&, Array&>);309 static_assert(std::convertible_to<Array&, const Array&>);310 static_assert(!std::convertible_to<const Array&, Array&>);311 static_assert(std::convertible_to<const Array&, const Array&>);312 313 CheckNotConvertibleTo<Array&, char>();314 CheckNotConvertibleTo<Array&, char&>();315 316 static_assert(std::convertible_to<Array&, char*>);317 static_assert(std::convertible_to<Array&, const char*>);318 static_assert(!std::convertible_to<const Array&, char*>);319 static_assert(std::convertible_to<const Array&, const char*>);320 321 static_assert(std::convertible_to<Array, StringType>);322 static_assert(std::convertible_to<char(&)[], StringType>);323 324 // char325 CheckNotConvertibleTo<char, void>();326 CheckNotConvertibleTo<char, Function>();327 CheckNotConvertibleTo<char, Function&>();328 CheckNotConvertibleTo<char, Function*>();329 CheckNotConvertibleTo<char, NoexceptFunction>();330 CheckNotConvertibleTo<char, NoexceptFunction&>();331 CheckNotConvertibleTo<char, NoexceptFunction*>();332 CheckNotConvertibleTo<char, Array>();333 CheckNotConvertibleTo<char, Array&>();334 335 CheckConvertibleTo<char, char>();336 337 static_assert(!std::convertible_to<char, char&>);338 static_assert(std::convertible_to<char, const char&>);339 static_assert(!std::convertible_to<const char, char&>);340 static_assert(std::convertible_to<const char, const char&>);341 342 CheckNotConvertibleTo<char, char*>();343 344 // char&345 CheckNotConvertibleTo<char&, void>();346 CheckNotConvertibleTo<char&, Function>();347 CheckNotConvertibleTo<char&, Function&>();348 CheckNotConvertibleTo<char&, Function*>();349 CheckNotConvertibleTo<char&, NoexceptFunction>();350 CheckNotConvertibleTo<char&, NoexceptFunction&>();351 CheckNotConvertibleTo<char&, NoexceptFunction*>();352 CheckNotConvertibleTo<char&, Array>();353 CheckNotConvertibleTo<char&, Array&>();354 355 CheckConvertibleTo<char&, char>();356 357 static_assert(std::convertible_to<char&, char&>);358 static_assert(std::convertible_to<char&, const char&>);359 static_assert(!std::convertible_to<const char&, char&>);360 static_assert(std::convertible_to<const char&, const char&>);361 362 CheckNotConvertibleTo<char&, char*>();363 364 // char*365 CheckNotConvertibleTo<char*, void>();366 CheckNotConvertibleTo<char*, Function>();367 CheckNotConvertibleTo<char*, Function&>();368 CheckNotConvertibleTo<char*, Function*>();369 CheckNotConvertibleTo<char*, NoexceptFunction>();370 CheckNotConvertibleTo<char*, NoexceptFunction&>();371 CheckNotConvertibleTo<char*, NoexceptFunction*>();372 CheckNotConvertibleTo<char*, Array>();373 CheckNotConvertibleTo<char*, Array&>();374 375 CheckNotConvertibleTo<char*, char>();376 CheckNotConvertibleTo<char*, char&>();377 378 static_assert(std::convertible_to<char*, char*>);379 static_assert(std::convertible_to<char*, const char*>);380 static_assert(!std::convertible_to<const char*, char*>);381 static_assert(std::convertible_to<const char*, const char*>);382 383 // NonCopyable384 static_assert(std::convertible_to<NonCopyable&, NonCopyable&>);385 static_assert(std::convertible_to<NonCopyable&, const NonCopyable&>);386 static_assert(std::convertible_to<NonCopyable&, const volatile NonCopyable&>);387 static_assert(std::convertible_to<NonCopyable&, volatile NonCopyable&>);388 static_assert(std::convertible_to<const NonCopyable&, const NonCopyable&>);389 static_assert(390 std::convertible_to<const NonCopyable&, const volatile NonCopyable&>);391 static_assert(392 std::convertible_to<volatile NonCopyable&, const volatile NonCopyable&>);393 static_assert(std::convertible_to<const volatile NonCopyable&,394 const volatile NonCopyable&>);395 static_assert(!std::convertible_to<const NonCopyable&, NonCopyable&>);396 397 // This test requires Access control SFINAE which we only have in C++11 or when398 // we are using the compiler builtin for convertible_to.399 CheckNotConvertibleTo<NonCopyable&, NonCopyable>();400 401 // Ensure that CannotInstantiate is not instantiated by convertible_to when it is not needed.402 // For example CannotInstantiate is instantiated as a part of ADL lookup for arguments of type CannotInstantiate*.403 static_assert(404 std::convertible_to<CannotInstantiate<int>*, CannotInstantiate<int>*>);405 406 // Test for PR13592407 static_assert(!std::convertible_to<abstract, abstract>);408 409 CommonlyNotConvertibleTo<int>();410 CommonlyNotConvertibleTo<bool>();411 CommonlyNotConvertibleTo<nullptr_t>();412 413 CheckNotConvertibleTo<int, ExplicitlyConstructible>();414 CheckNotConvertibleTo<ExplicitlyConvertible, ExplicitlyConstructible>();415 CheckNotConvertibleTo<ExplicitlyConstructible, ExplicitlyConvertible>();416 CheckIsConvertibleButNotConvertibleTo<ImplicitlyConvertible,417 ExplicitlyConstructible>();418 CheckNotConvertibleTo<ImplicitlyConstructible, ImplicitlyConvertible>();419 420 return 0;421}422