1*24dd2d2fSChristopher Di Bella //===----------------------------------------------------------------------===// 2*24dd2d2fSChristopher Di Bella // 3*24dd2d2fSChristopher Di Bella // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*24dd2d2fSChristopher Di Bella // See https://llvm.org/LICENSE.txt for license information. 5*24dd2d2fSChristopher Di Bella // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*24dd2d2fSChristopher Di Bella // 7*24dd2d2fSChristopher Di Bella //===----------------------------------------------------------------------===// 8*24dd2d2fSChristopher Di Bella 9*24dd2d2fSChristopher Di Bella // UNSUPPORTED: c++03, c++11, c++14, c++17 10*24dd2d2fSChristopher Di Bella // UNSUPPORTED: libcpp-no-concepts 11*24dd2d2fSChristopher Di Bella 12*24dd2d2fSChristopher Di Bella // template<class T, class U> 13*24dd2d2fSChristopher Di Bella // concept same_as; 14*24dd2d2fSChristopher Di Bella 15*24dd2d2fSChristopher Di Bella #include <concepts> 16*24dd2d2fSChristopher Di Bella #include <type_traits> 17*24dd2d2fSChristopher Di Bella 18*24dd2d2fSChristopher Di Bella struct S1 {}; 19*24dd2d2fSChristopher Di Bella struct S2 { 20*24dd2d2fSChristopher Di Bella int i; 21*24dd2d2fSChristopher Di Bella 22*24dd2d2fSChristopher Di Bella int& f(); 23*24dd2d2fSChristopher Di Bella double g(int x) const; 24*24dd2d2fSChristopher Di Bella }; 25*24dd2d2fSChristopher Di Bella struct S3 { 26*24dd2d2fSChristopher Di Bella int& r; 27*24dd2d2fSChristopher Di Bella }; 28*24dd2d2fSChristopher Di Bella struct S4 { 29*24dd2d2fSChristopher Di Bella int&& r; 30*24dd2d2fSChristopher Di Bella }; 31*24dd2d2fSChristopher Di Bella struct S5 { 32*24dd2d2fSChristopher Di Bella int* p; 33*24dd2d2fSChristopher Di Bella }; 34*24dd2d2fSChristopher Di Bella 35*24dd2d2fSChristopher Di Bella class C1 {}; 36*24dd2d2fSChristopher Di Bella class C2 { 37*24dd2d2fSChristopher Di Bella [[maybe_unused]] int i; 38*24dd2d2fSChristopher Di Bella }; 39*24dd2d2fSChristopher Di Bella 40*24dd2d2fSChristopher Di Bella class C3 { 41*24dd2d2fSChristopher Di Bella public: 42*24dd2d2fSChristopher Di Bella int i; 43*24dd2d2fSChristopher Di Bella }; 44*24dd2d2fSChristopher Di Bella 45*24dd2d2fSChristopher Di Bella template <class T1, class T2 = T1> 46*24dd2d2fSChristopher Di Bella class C4 { 47*24dd2d2fSChristopher Di Bella int t1; 48*24dd2d2fSChristopher Di Bella int t2; 49*24dd2d2fSChristopher Di Bella }; 50*24dd2d2fSChristopher Di Bella 51*24dd2d2fSChristopher Di Bella template <class T1, class T2 = T1> 52*24dd2d2fSChristopher Di Bella class C5 { 53*24dd2d2fSChristopher Di Bella [[maybe_unused]] T1 t1; 54*24dd2d2fSChristopher Di Bella 55*24dd2d2fSChristopher Di Bella public: 56*24dd2d2fSChristopher Di Bella T2 t2; 57*24dd2d2fSChristopher Di Bella }; 58*24dd2d2fSChristopher Di Bella 59*24dd2d2fSChristopher Di Bella template <class T1, class T2 = T1> 60*24dd2d2fSChristopher Di Bella class C6 { 61*24dd2d2fSChristopher Di Bella public: 62*24dd2d2fSChristopher Di Bella [[maybe_unused]] T1 t1; 63*24dd2d2fSChristopher Di Bella [[maybe_unused]] T2 t2; 64*24dd2d2fSChristopher Di Bella }; 65*24dd2d2fSChristopher Di Bella 66*24dd2d2fSChristopher Di Bella template <class T> 67*24dd2d2fSChristopher Di Bella struct identity { 68*24dd2d2fSChristopher Di Bella using type = T; 69*24dd2d2fSChristopher Di Bella }; 70*24dd2d2fSChristopher Di Bella 71*24dd2d2fSChristopher Di Bella template <template <typename> class Modifier = identity> 72*24dd2d2fSChristopher Di Bella void CheckSameAs() { 73*24dd2d2fSChristopher Di Bella static_assert( 74*24dd2d2fSChristopher Di Bella std::same_as<typename Modifier<int>::type, typename Modifier<int>::type>); 75*24dd2d2fSChristopher Di Bella static_assert( 76*24dd2d2fSChristopher Di Bella std::same_as<typename Modifier<S1>::type, typename Modifier<S1>::type>); 77*24dd2d2fSChristopher Di Bella static_assert( 78*24dd2d2fSChristopher Di Bella std::same_as<typename Modifier<S2>::type, typename Modifier<S2>::type>); 79*24dd2d2fSChristopher Di Bella static_assert( 80*24dd2d2fSChristopher Di Bella std::same_as<typename Modifier<S3>::type, typename Modifier<S3>::type>); 81*24dd2d2fSChristopher Di Bella static_assert( 82*24dd2d2fSChristopher Di Bella std::same_as<typename Modifier<S4>::type, typename Modifier<S4>::type>); 83*24dd2d2fSChristopher Di Bella static_assert( 84*24dd2d2fSChristopher Di Bella std::same_as<typename Modifier<S5>::type, typename Modifier<S5>::type>); 85*24dd2d2fSChristopher Di Bella static_assert( 86*24dd2d2fSChristopher Di Bella std::same_as<typename Modifier<C1>::type, typename Modifier<C1>::type>); 87*24dd2d2fSChristopher Di Bella static_assert( 88*24dd2d2fSChristopher Di Bella std::same_as<typename Modifier<C2>::type, typename Modifier<C2>::type>); 89*24dd2d2fSChristopher Di Bella static_assert( 90*24dd2d2fSChristopher Di Bella std::same_as<typename Modifier<C3>::type, typename Modifier<C3>::type>); 91*24dd2d2fSChristopher Di Bella static_assert(std::same_as<typename Modifier<C4<int> >::type, 92*24dd2d2fSChristopher Di Bella typename Modifier<C4<int> >::type>); 93*24dd2d2fSChristopher Di Bella static_assert(std::same_as<typename Modifier<C4<int&> >::type, 94*24dd2d2fSChristopher Di Bella typename Modifier<C4<int&> >::type>); 95*24dd2d2fSChristopher Di Bella static_assert(std::same_as<typename Modifier<C4<int&&> >::type, 96*24dd2d2fSChristopher Di Bella typename Modifier<C4<int&&> >::type>); 97*24dd2d2fSChristopher Di Bella static_assert(std::same_as<typename Modifier<C5<int> >::type, 98*24dd2d2fSChristopher Di Bella typename Modifier<C5<int> >::type>); 99*24dd2d2fSChristopher Di Bella static_assert(std::same_as<typename Modifier<C5<int&> >::type, 100*24dd2d2fSChristopher Di Bella typename Modifier<C5<int&> >::type>); 101*24dd2d2fSChristopher Di Bella static_assert(std::same_as<typename Modifier<C5<int&&> >::type, 102*24dd2d2fSChristopher Di Bella typename Modifier<C5<int&&> >::type>); 103*24dd2d2fSChristopher Di Bella static_assert(std::same_as<typename Modifier<C6<int> >::type, 104*24dd2d2fSChristopher Di Bella typename Modifier<C6<int> >::type>); 105*24dd2d2fSChristopher Di Bella static_assert(std::same_as<typename Modifier<C6<int&> >::type, 106*24dd2d2fSChristopher Di Bella typename Modifier<C6<int&> >::type>); 107*24dd2d2fSChristopher Di Bella static_assert(std::same_as<typename Modifier<C6<int&&> >::type, 108*24dd2d2fSChristopher Di Bella typename Modifier<C6<int&&> >::type>); 109*24dd2d2fSChristopher Di Bella 110*24dd2d2fSChristopher Di Bella static_assert(std::same_as<typename Modifier<void>::type, 111*24dd2d2fSChristopher Di Bella typename Modifier<void>::type>); 112*24dd2d2fSChristopher Di Bella } 113*24dd2d2fSChristopher Di Bella 114*24dd2d2fSChristopher Di Bella template <template <typename> class Modifier1, 115*24dd2d2fSChristopher Di Bella template <typename> class Modifier2> 116*24dd2d2fSChristopher Di Bella void CheckNotSameAs() { 117*24dd2d2fSChristopher Di Bella static_assert(!std::same_as<typename Modifier1<int>::type, 118*24dd2d2fSChristopher Di Bella typename Modifier2<int>::type>); 119*24dd2d2fSChristopher Di Bella static_assert(!std::same_as<typename Modifier1<S1>::type, 120*24dd2d2fSChristopher Di Bella typename Modifier2<S1>::type>); 121*24dd2d2fSChristopher Di Bella static_assert(!std::same_as<typename Modifier1<S2>::type, 122*24dd2d2fSChristopher Di Bella typename Modifier2<S2>::type>); 123*24dd2d2fSChristopher Di Bella static_assert(!std::same_as<typename Modifier1<S3>::type, 124*24dd2d2fSChristopher Di Bella typename Modifier2<S3>::type>); 125*24dd2d2fSChristopher Di Bella static_assert(!std::same_as<typename Modifier1<S4>::type, 126*24dd2d2fSChristopher Di Bella typename Modifier2<S4>::type>); 127*24dd2d2fSChristopher Di Bella static_assert(!std::same_as<typename Modifier1<S5>::type, 128*24dd2d2fSChristopher Di Bella typename Modifier2<S5>::type>); 129*24dd2d2fSChristopher Di Bella static_assert(!std::same_as<typename Modifier1<C1>::type, 130*24dd2d2fSChristopher Di Bella typename Modifier2<C1>::type>); 131*24dd2d2fSChristopher Di Bella static_assert(!std::same_as<typename Modifier1<C2>::type, 132*24dd2d2fSChristopher Di Bella typename Modifier2<C2>::type>); 133*24dd2d2fSChristopher Di Bella static_assert(!std::same_as<typename Modifier1<C3>::type, 134*24dd2d2fSChristopher Di Bella typename Modifier2<C3>::type>); 135*24dd2d2fSChristopher Di Bella static_assert(!std::same_as<typename Modifier1<C4<int> >::type, 136*24dd2d2fSChristopher Di Bella typename Modifier2<C4<int> >::type>); 137*24dd2d2fSChristopher Di Bella static_assert(!std::same_as<typename Modifier1<C4<int&> >::type, 138*24dd2d2fSChristopher Di Bella typename Modifier2<C4<int&> >::type>); 139*24dd2d2fSChristopher Di Bella static_assert(!std::same_as<typename Modifier1<C4<int&&> >::type, 140*24dd2d2fSChristopher Di Bella typename Modifier2<C4<int&&> >::type>); 141*24dd2d2fSChristopher Di Bella static_assert(!std::same_as<typename Modifier1<C5<int> >::type, 142*24dd2d2fSChristopher Di Bella typename Modifier2<C5<int> >::type>); 143*24dd2d2fSChristopher Di Bella static_assert(!std::same_as<typename Modifier1<C5<int&> >::type, 144*24dd2d2fSChristopher Di Bella typename Modifier2<C5<int&> >::type>); 145*24dd2d2fSChristopher Di Bella static_assert(!std::same_as<typename Modifier1<C5<int&&> >::type, 146*24dd2d2fSChristopher Di Bella typename Modifier2<C5<int&&> >::type>); 147*24dd2d2fSChristopher Di Bella static_assert(!std::same_as<typename Modifier1<C6<int> >::type, 148*24dd2d2fSChristopher Di Bella typename Modifier2<C6<int> >::type>); 149*24dd2d2fSChristopher Di Bella static_assert(!std::same_as<typename Modifier1<C6<int&> >::type, 150*24dd2d2fSChristopher Di Bella typename Modifier2<C6<int&> >::type>); 151*24dd2d2fSChristopher Di Bella static_assert(!std::same_as<typename Modifier1<C6<int&&> >::type, 152*24dd2d2fSChristopher Di Bella typename Modifier2<C6<int&&> >::type>); 153*24dd2d2fSChristopher Di Bella } 154*24dd2d2fSChristopher Di Bella 155*24dd2d2fSChristopher Di Bella // Checks subsumption works as intended 156*24dd2d2fSChristopher Di Bella template <class T, class U> 157*24dd2d2fSChristopher Di Bella requires std::same_as<T, U> void SubsumptionTest(); 158*24dd2d2fSChristopher Di Bella 159*24dd2d2fSChristopher Di Bella // clang-format off 160*24dd2d2fSChristopher Di Bella template <class T, class U> 161*24dd2d2fSChristopher Di Bella requires std::same_as<U, T> && true // NOLINT(readability-simplify-boolean-expr) 162*24dd2d2fSChristopher Di Bella int SubsumptionTest(); 163*24dd2d2fSChristopher Di Bella // clang-format on 164*24dd2d2fSChristopher Di Bella 165*24dd2d2fSChristopher Di Bella static_assert(std::same_as<int, decltype(SubsumptionTest<int, int>())>); 166*24dd2d2fSChristopher Di Bella static_assert(std::same_as<int, decltype(SubsumptionTest<void, void>())>); 167*24dd2d2fSChristopher Di Bella static_assert( 168*24dd2d2fSChristopher Di Bella std::same_as<int, decltype(SubsumptionTest<int (*)(), int (*)()>())>); 169*24dd2d2fSChristopher Di Bella static_assert( 170*24dd2d2fSChristopher Di Bella std::same_as< 171*24dd2d2fSChristopher Di Bella int, decltype(SubsumptionTest<double (&)(int), double (&)(int)>())>); 172*24dd2d2fSChristopher Di Bella static_assert( 173*24dd2d2fSChristopher Di Bella std::same_as<int, decltype(SubsumptionTest<int S2::*, int S2::*>())>); 174*24dd2d2fSChristopher Di Bella static_assert( 175*24dd2d2fSChristopher Di Bella std::same_as<int, 176*24dd2d2fSChristopher Di Bella decltype(SubsumptionTest<int& (S2::*)(), int& (S2::*)()>())>); 177*24dd2d2fSChristopher Di Bella 178*24dd2d2fSChristopher Di Bella int main(int, char**) { 179*24dd2d2fSChristopher Di Bella { // Checks std::same_as<T, T> is true 180*24dd2d2fSChristopher Di Bella CheckSameAs(); 181*24dd2d2fSChristopher Di Bella 182*24dd2d2fSChristopher Di Bella // Checks std::same_as<T&, T&> is true 183*24dd2d2fSChristopher Di Bella CheckSameAs<std::add_lvalue_reference>(); 184*24dd2d2fSChristopher Di Bella 185*24dd2d2fSChristopher Di Bella // Checks std::same_as<T&&, T&&> is true 186*24dd2d2fSChristopher Di Bella CheckSameAs<std::add_rvalue_reference>(); 187*24dd2d2fSChristopher Di Bella 188*24dd2d2fSChristopher Di Bella // Checks std::same_as<const T, const T> is true 189*24dd2d2fSChristopher Di Bella CheckSameAs<std::add_const>(); 190*24dd2d2fSChristopher Di Bella 191*24dd2d2fSChristopher Di Bella // Checks std::same_as<volatile T, volatile T> is true 192*24dd2d2fSChristopher Di Bella CheckSameAs<std::add_volatile>(); 193*24dd2d2fSChristopher Di Bella 194*24dd2d2fSChristopher Di Bella // Checks std::same_as<const volatile T, const volatile T> is true 195*24dd2d2fSChristopher Di Bella CheckSameAs<std::add_cv>(); 196*24dd2d2fSChristopher Di Bella 197*24dd2d2fSChristopher Di Bella // Checks std::same_as<T*, T*> is true 198*24dd2d2fSChristopher Di Bella CheckSameAs<std::add_pointer>(); 199*24dd2d2fSChristopher Di Bella 200*24dd2d2fSChristopher Di Bella // Checks concrete types are identical 201*24dd2d2fSChristopher Di Bella static_assert(std::same_as<void, void>); 202*24dd2d2fSChristopher Di Bella 203*24dd2d2fSChristopher Di Bella using Void = void; 204*24dd2d2fSChristopher Di Bella static_assert(std::same_as<void, Void>); 205*24dd2d2fSChristopher Di Bella 206*24dd2d2fSChristopher Di Bella static_assert(std::same_as<int[1], int[1]>); 207*24dd2d2fSChristopher Di Bella static_assert(std::same_as<int[2], int[2]>); 208*24dd2d2fSChristopher Di Bella 209*24dd2d2fSChristopher Di Bella static_assert(std::same_as<int (*)(), int (*)()>); 210*24dd2d2fSChristopher Di Bella static_assert(std::same_as<void (&)(), void (&)()>); 211*24dd2d2fSChristopher Di Bella static_assert(std::same_as<S1& (*)(S1), S1& (*)(S1)>); 212*24dd2d2fSChristopher Di Bella static_assert(std::same_as<C1& (&)(S1, int), C1& (&)(S1, int)>); 213*24dd2d2fSChristopher Di Bella 214*24dd2d2fSChristopher Di Bella static_assert(std::same_as<int S2::*, int S2::*>); 215*24dd2d2fSChristopher Di Bella static_assert(std::same_as<double S2::*, double S2::*>); 216*24dd2d2fSChristopher Di Bella 217*24dd2d2fSChristopher Di Bella static_assert(std::same_as<int& (S2::*)(), int& (S2::*)()>); 218*24dd2d2fSChristopher Di Bella static_assert(std::same_as<double& (S2::*)(int), double& (S2::*)(int)>); 219*24dd2d2fSChristopher Di Bella } 220*24dd2d2fSChristopher Di Bella 221*24dd2d2fSChristopher Di Bella { // Checks that `T` and `T&` are distinct types 222*24dd2d2fSChristopher Di Bella CheckNotSameAs<identity, std::add_lvalue_reference>(); 223*24dd2d2fSChristopher Di Bella CheckNotSameAs<std::add_lvalue_reference, identity>(); 224*24dd2d2fSChristopher Di Bella 225*24dd2d2fSChristopher Di Bella // Checks that `T` and `T&&` are distinct types 226*24dd2d2fSChristopher Di Bella CheckNotSameAs<identity, std::add_rvalue_reference>(); 227*24dd2d2fSChristopher Di Bella CheckNotSameAs<std::add_rvalue_reference, identity>(); 228*24dd2d2fSChristopher Di Bella 229*24dd2d2fSChristopher Di Bella // Checks that `T` and `const T` are distinct types 230*24dd2d2fSChristopher Di Bella CheckNotSameAs<identity, std::add_const>(); 231*24dd2d2fSChristopher Di Bella CheckNotSameAs<std::add_const, identity>(); 232*24dd2d2fSChristopher Di Bella 233*24dd2d2fSChristopher Di Bella // Checks that `T` and `volatile T` are distinct types 234*24dd2d2fSChristopher Di Bella CheckNotSameAs<identity, std::add_volatile>(); 235*24dd2d2fSChristopher Di Bella CheckNotSameAs<std::add_volatile, identity>(); 236*24dd2d2fSChristopher Di Bella 237*24dd2d2fSChristopher Di Bella // Checks that `T` and `const volatile T` are distinct types 238*24dd2d2fSChristopher Di Bella CheckNotSameAs<identity, std::add_cv>(); 239*24dd2d2fSChristopher Di Bella CheckNotSameAs<std::add_cv, identity>(); 240*24dd2d2fSChristopher Di Bella 241*24dd2d2fSChristopher Di Bella // Checks that `const T` and `volatile T` are distinct types 242*24dd2d2fSChristopher Di Bella CheckNotSameAs<std::add_const, std::add_volatile>(); 243*24dd2d2fSChristopher Di Bella CheckNotSameAs<std::add_volatile, std::add_const>(); 244*24dd2d2fSChristopher Di Bella 245*24dd2d2fSChristopher Di Bella // Checks that `const T` and `const volatile T` are distinct types 246*24dd2d2fSChristopher Di Bella CheckNotSameAs<std::add_const, std::add_cv>(); 247*24dd2d2fSChristopher Di Bella CheckNotSameAs<std::add_cv, std::add_const>(); 248*24dd2d2fSChristopher Di Bella 249*24dd2d2fSChristopher Di Bella // Checks that `volatile T` and `const volatile T` are distinct types 250*24dd2d2fSChristopher Di Bella CheckNotSameAs<std::add_volatile, std::add_cv>(); 251*24dd2d2fSChristopher Di Bella CheckNotSameAs<std::add_cv, std::add_volatile>(); 252*24dd2d2fSChristopher Di Bella 253*24dd2d2fSChristopher Di Bella // Checks `T&` and `T&&` are distinct types 254*24dd2d2fSChristopher Di Bella CheckNotSameAs<std::add_lvalue_reference, std::add_rvalue_reference>(); 255*24dd2d2fSChristopher Di Bella CheckNotSameAs<std::add_rvalue_reference, std::add_lvalue_reference>(); 256*24dd2d2fSChristopher Di Bella } 257*24dd2d2fSChristopher Di Bella 258*24dd2d2fSChristopher Di Bella { // Checks different type names are distinct types 259*24dd2d2fSChristopher Di Bella static_assert(!std::same_as<S1, C1>); 260*24dd2d2fSChristopher Di Bella static_assert(!std::same_as<C4<int>, C5<int> >); 261*24dd2d2fSChristopher Di Bella static_assert(!std::same_as<C4<int>, C5<int> >); 262*24dd2d2fSChristopher Di Bella static_assert(!std::same_as<C5<int, double>, C5<double, int> >); 263*24dd2d2fSChristopher Di Bella 264*24dd2d2fSChristopher Di Bella static_assert(!std::same_as<int&, const int&>); 265*24dd2d2fSChristopher Di Bella static_assert(!std::same_as<int&, volatile int&>); 266*24dd2d2fSChristopher Di Bella static_assert(!std::same_as<int&, const volatile int&>); 267*24dd2d2fSChristopher Di Bella 268*24dd2d2fSChristopher Di Bella static_assert(!std::same_as<int&&, const int&>); 269*24dd2d2fSChristopher Di Bella static_assert(!std::same_as<int&&, volatile int&>); 270*24dd2d2fSChristopher Di Bella static_assert(!std::same_as<int&&, const volatile int&>); 271*24dd2d2fSChristopher Di Bella 272*24dd2d2fSChristopher Di Bella static_assert(!std::same_as<int&, const int&&>); 273*24dd2d2fSChristopher Di Bella static_assert(!std::same_as<int&, volatile int&&>); 274*24dd2d2fSChristopher Di Bella static_assert(!std::same_as<int&, const volatile int&&>); 275*24dd2d2fSChristopher Di Bella 276*24dd2d2fSChristopher Di Bella static_assert(!std::same_as<int&&, const int&&>); 277*24dd2d2fSChristopher Di Bella static_assert(!std::same_as<int&&, volatile int&&>); 278*24dd2d2fSChristopher Di Bella static_assert(!std::same_as<int&&, const volatile int&&>); 279*24dd2d2fSChristopher Di Bella 280*24dd2d2fSChristopher Di Bella static_assert(!std::same_as<void, int>); 281*24dd2d2fSChristopher Di Bella 282*24dd2d2fSChristopher Di Bella static_assert(!std::same_as<int[1], int[2]>); 283*24dd2d2fSChristopher Di Bella static_assert(!std::same_as<double[1], int[2]>); 284*24dd2d2fSChristopher Di Bella 285*24dd2d2fSChristopher Di Bella static_assert(!std::same_as<int* (*)(), const int* (*)()>); 286*24dd2d2fSChristopher Di Bella static_assert(!std::same_as<void (&)(), void (&)(S1)>); 287*24dd2d2fSChristopher Di Bella static_assert(!std::same_as<S1 (*)(S1), S1& (*)(S1)>); 288*24dd2d2fSChristopher Di Bella static_assert(!std::same_as<C3 (&)(int), C1& (&)(S1, int)>); 289*24dd2d2fSChristopher Di Bella 290*24dd2d2fSChristopher Di Bella static_assert(!std::same_as<int S2::*, double S2::*>); 291*24dd2d2fSChristopher Di Bella 292*24dd2d2fSChristopher Di Bella static_assert(!std::same_as<int& (S2::*)(), double& (S2::*)(int)>); 293*24dd2d2fSChristopher Di Bella } 294*24dd2d2fSChristopher Di Bella 295*24dd2d2fSChristopher Di Bella return 0; 296*24dd2d2fSChristopher Di Bella } 297