diff options
Diffstat (limited to 'indra/newview/tests')
| -rw-r--r-- | indra/newview/tests/cppfeatures_test.cpp | 372 | 
1 files changed, 245 insertions, 127 deletions
| diff --git a/indra/newview/tests/cppfeatures_test.cpp b/indra/newview/tests/cppfeatures_test.cpp index 15aa1cd6d6..8399bb12ff 100644 --- a/indra/newview/tests/cppfeatures_test.cpp +++ b/indra/newview/tests/cppfeatures_test.cpp @@ -1,127 +1,245 @@ -/**
 - * @file cppfeatures_test
 - * @author Vir
 - * @date 2021-03
 - * @brief cpp features
 - *
 - * $LicenseInfo:firstyear=2021&license=viewerlgpl$
 - * Second Life Viewer Source Code
 - * Copyright (C) 2021, Linden Research, Inc.
 - * 
 - * This library is free software; you can redistribute it and/or
 - * modify it under the terms of the GNU Lesser General Public
 - * License as published by the Free Software Foundation;
 - * version 2.1 of the License only.
 - * 
 - * This library is distributed in the hope that it will be useful,
 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 - * Lesser General Public License for more details.
 - * 
 - * You should have received a copy of the GNU Lesser General Public
 - * License along with this library; if not, write to the Free Software
 - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 - * 
 - * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 - * $/LicenseInfo$
 - */
 -
 -// Tests related to newer C++ features, for verifying support across compilers and platforms
 -
 -#include "linden_common.h"
 -#include "../test/lltut.h"
 -
 -namespace tut
 -{
 -
 -struct cpp_features_test {};
 -typedef test_group<cpp_features_test> cpp_features_test_t;
 -typedef cpp_features_test_t::object cpp_features_test_object_t;
 -tut::cpp_features_test_t tut_cpp_features_test("LLCPPFeatures");
 -
 -// bracket initializers
 -// Can initialize containers or values using curly brackets
 -template<> template<>
 -void cpp_features_test_object_t::test<1>()
 -{
 -	S32 explicit_val{3};
 -	ensure(explicit_val==3);
 -
 -	S32 default_val{};
 -	ensure(default_val==0);
 -	
 -	std::vector<S32> fibs{1,1,2,3,5};
 -	ensure(fibs[4]==5);
 -}
 -
 -// auto
 -//
 -// https://en.cppreference.com/w/cpp/language/auto
 -// 
 -// Can use auto in place of a more complex type specification, if the compiler can infer the type
 -template<> template<>
 -void cpp_features_test_object_t::test<2>()
 -{
 -	std::vector<S32> numbers{3,6,9};
 -
 -	// auto element
 -	auto& aval = numbers[1];
 -	ensure("auto element", aval==6);
 -
 -	// auto iterator (non-const)
 -	auto it = numbers.rbegin();
 -	*it += 1;
 -	S32 val = *it;
 -	ensure("auto iterator", val==10);
 -}
 -
 -// range for
 -//
 -// https://en.cppreference.com/w/cpp/language/range-for
 -//
 -// Can iterate over containers without explicit iterator
 -template<> template<>
 -void cpp_features_test_object_t::test<3>()
 -{
 -
 -	// Traditional iterator for with container
 -	//
 -	// Problems:
 -	// * Have to create a new variable for the iterator, which is unrelated to the problem you're trying to solve.
 -	// * Redundant and somewhat fragile. Have to make sure begin() and end() are both from the right container.
 -	std::vector<S32> numbers{3,6,9};
 -	for (auto it = numbers.begin(); it != numbers.end(); ++it)
 -	{
 -		auto& n = *it;
 -		n *= 2;
 -	}
 -	ensure("iterator for vector", numbers[2]==18);
 -
 -	// Range for with container
 -	//
 -	// Under the hood, this is doing the same thing as the traditional
 -	// for loop above. Still uses begin() and end() but you don't have
 -	// to access them directly.
 -	std::vector<S32> numbersb{3,6,9};
 -	for (auto& n: numbersb)
 -	{
 -		n *= 2;
 -	}
 -	ensure("range for vector", numbersb[2]==18);
 -
 -	// Range for over a C-style array.
 -	//
 -	// This is handy because the language determines the range automatically.
 -	// Getting this right manually is a little trickier.
 -	S32 pows[] = {1,2,4,8,16};
 -	S32 sum{};
 -	for (const auto& v: pows)
 -	{
 -		sum += v;
 -	}
 -	ensure("for C-array", sum==31);
 -}
 -
 -
 -
 -}
 +/** + * @file cppfeatures_test + * @author Vir + * @date 2021-03 + * @brief cpp features + * + * $LicenseInfo:firstyear=2021&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2021, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +// Tests related to newer C++ features, for verifying support across compilers and platforms + +#include "linden_common.h" +#include "../test/lltut.h" + +namespace tut +{ + +struct cpp_features_test {}; +typedef test_group<cpp_features_test> cpp_features_test_t; +typedef cpp_features_test_t::object cpp_features_test_object_t; +tut::cpp_features_test_t tut_cpp_features_test("LLCPPFeatures"); + +// bracket initializers +// Can initialize containers or values using curly brackets +template<> template<> +void cpp_features_test_object_t::test<1>() +{ +	S32 explicit_val{3}; +	ensure(explicit_val==3); + +	S32 default_val{}; +	ensure(default_val==0); +	 +	std::vector<S32> fibs{1,1,2,3,5}; +	ensure(fibs[4]==5); +} + +// auto +// +// https://en.cppreference.com/w/cpp/language/auto +//  +// Can use auto in place of a more complex type specification, if the compiler can infer the type +template<> template<> +void cpp_features_test_object_t::test<2>() +{ +	std::vector<S32> numbers{3,6,9}; + +	// auto element +	auto& aval = numbers[1]; +	ensure("auto element", aval==6); + +	// auto iterator (non-const) +	auto it = numbers.rbegin(); +	*it += 1; +	S32 val = *it; +	ensure("auto iterator", val==10); +} + +// range for +// +// https://en.cppreference.com/w/cpp/language/range-for +// +// Can iterate over containers without explicit iterator +template<> template<> +void cpp_features_test_object_t::test<3>() +{ + +	// Traditional iterator for with container +	// +	// Problems: +	// * Have to create a new variable for the iterator, which is unrelated to the problem you're trying to solve. +	// * Redundant and somewhat fragile. Have to make sure begin() and end() are both from the right container. +	std::vector<S32> numbers{3,6,9}; +	for (auto it = numbers.begin(); it != numbers.end(); ++it) +	{ +		auto& n = *it; +		n *= 2; +	} +	ensure("iterator for vector", numbers[2]==18); + +	// Range for with container +	// +	// Under the hood, this is doing the same thing as the traditional +	// for loop above. Still uses begin() and end() but you don't have +	// to access them directly. +	std::vector<S32> numbersb{3,6,9}; +	for (auto& n: numbersb) +	{ +		n *= 2; +	} +	ensure("range for vector", numbersb[2]==18); + +	// Range for over a C-style array. +	// +	// This is handy because the language determines the range automatically. +	// Getting this right manually is a little trickier. +	S32 pows[] = {1,2,4,8,16}; +	S32 sum{}; +	for (const auto& v: pows) +	{ +		sum += v; +	} +	ensure("for C-array", sum==31); +} + +// override specifier +// +// https://en.cppreference.com/w/cpp/language/override +// +// Specify that a particular class function is an override of a virtual function. +// Benefits: +// * Makes code somewhat easier to read by showing intent. +// * Prevents mistakes where you think something is an override but it doesn't actually match the declaration in the parent class. +// Drawbacks: +// * Some compilers require that any class using override must use it consistently for all functions.  +//   This makes switching a class to use override a lot more work.  + +class Foo +{ +public: +	virtual bool is_happy() const = 0; +}; + +class Bar: public Foo +{ +public: +	bool is_happy() const override { return true; }  +	// Override would fail: non-const declaration doesn't match parent  +	// bool is_happy() override { return true; }  +	// Override would fail: wrong name +	// bool is_happx() override { return true; }  +}; + +template<> template<> +void cpp_features_test_object_t::test<4>() +{ +	Bar b; +	ensure("override", b.is_happy()); +} + +// final +// +// https://en.cppreference.com/w/cpp/language/final: "Specifies that a +// virtual function cannot be overridden in a derived class or that a +// class cannot be inherited from." + +class Vehicle +{ +public: +	virtual bool has_wheels() const = 0; +}; + +class WheeledVehicle: public Vehicle +{ +public: +	virtual bool has_wheels() const final override { return true; } +}; + +class Bicycle: public WheeledVehicle +{ +public: +	// Error: can't override final version in WheeledVehicle  +	// virtual bool has_wheels() override const { return true; } +}; + +template<> template<> +void cpp_features_test_object_t::test<5>() +{ +	Bicycle bi; +	ensure("final", bi.has_wheels()); +} + +// deleted function declaration +// +// https://en.cppreference.com/w/cpp/language/function#Deleted_functions +// +// Typical case: copy constructor doesn't make sense for a particular class, so you want to make +// sure the no one tries to copy-construct an instance of the class, and that the +// compiler won't generate a copy constructor for  you automatically. +// Traditional fix is to declare a +// copy constructor but never implement it, giving you a link-time error if anyone tries to use it. +// Now you can explicitly declare a function to be deleted, which has at least two advantages over +// the old way: +// * Makes the intention clear +// * Creates an error sooner, at compile time + +class DoNotCopy +{ +public: +	DoNotCopy() {} +	DoNotCopy(const DoNotCopy& ref) = delete; +}; + +template<> template<> +void cpp_features_test_object_t::test<6>() +{ +	DoNotCopy nc; // OK, default constructor +	//DoNotCopy nc2(nc); // No, can't copy +	//DoNotCopy nc3 = nc; // No, this also calls copy constructor (even though it looks like an assignment) +} + +// defaulted function declaration +// +// https://en.cppreference.com/w/cpp/language/function#Function_definition +// +// What about the complementary case to the deleted function declaration, where you want a copy constructor +// and are happy with the default implementation the compiler will make (memberwise copy). +// Now you can explicitly declare that too. +// Usage: I guess it makes the intent clearer, but otherwise not obviously useful. +class DefaultCopyOK +{ +public: +	DefaultCopyOK() {} +	DefaultCopyOK(const DefaultCopyOK&) = default; +}; + +template<> template<> +void cpp_features_test_object_t::test<7>() +{ +	DefaultCopyOK d; // OK +	DefaultCopyOK d2(d); // OK +	DefaultCopyOK d3 = d; // OK +} + + +} // namespace tut | 
