/* Copyright (c) 2021 Intel Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #ifndef __TBB_test_common_concepts_common_H #define __TBB_test_common_concepts_common_H #include "tbb/parallel_pipeline.h" #include "tbb/parallel_for_each.h" #include "tbb/flow_graph.h" #include "tbb/parallel_scan.h" #include "iterator.h" #include #if __TBB_CPP20_CONCEPTS_PRESENT namespace test_concepts { struct Dummy {}; enum class State { correct, incorrect_first_input, incorrect_second_input, incorrect_third_input, incorrect_return_type, incorrect_constness, not_defined, incorrect, non_constant_expression }; struct Copyable { Copyable( const Copyable& ) = default; }; struct NonCopyable { NonCopyable( const NonCopyable& ) = delete; }; struct CopyAssignable { CopyAssignable& operator=( const CopyAssignable& ) = default; }; struct NonCopyAssignable { NonCopyAssignable& operator=( const NonCopyAssignable& ) = delete; }; struct DefaultInitializable { DefaultInitializable() = default; }; struct NonDefaultInitializable { NonDefaultInitializable() = delete; }; namespace blocked_range_value { template struct BlockedRangeValue { BlockedRangeValue( const BlockedRangeValue& ) requires EnableCopyCtor = default; BlockedRangeValue& operator=( const BlockedRangeValue& ) requires EnableCopyAssignment = default; // Prospective destructors ~BlockedRangeValue() requires EnableDtor = default; ~BlockedRangeValue() = delete; bool operator<( const BlockedRangeValue& ) const requires (EnableOperatorLess == State::correct) { return true; } bool operator<( Dummy ) const requires (EnableOperatorLess == State::incorrect_first_input) { return true; } Dummy operator<( const BlockedRangeValue& ) const requires (EnableOperatorLess == State::incorrect_return_type) { return Dummy{}; } bool operator<( const BlockedRangeValue& ) requires (EnableOperatorLess == State::incorrect_constness) { return true; } std::size_t operator-( const BlockedRangeValue& ) const requires (EnableOperatorMinus == State::correct) { return 0; } std::size_t operator-( Dummy ) const requires (EnableOperatorMinus == State::incorrect_first_input) { return 0; } Dummy operator-( const BlockedRangeValue& ) const requires (EnableOperatorMinus == State::incorrect_return_type) { return Dummy{}; } std::size_t operator-( const BlockedRangeValue& ) requires (EnableOperatorMinus == State::incorrect_constness) { return 0; } BlockedRangeValue operator+( std::size_t ) const requires (EnableOperatorPlusSizeT == State::correct) { return *this; } BlockedRangeValue operator+( Dummy ) const requires (EnableOperatorPlusSizeT == State::incorrect_first_input) { return *this; } Dummy operator+( std::size_t ) const requires (EnableOperatorPlusSizeT == State::incorrect_return_type) { return Dummy{}; } BlockedRangeValue operator+( std::size_t ) requires (EnableOperatorPlusSizeT == State::incorrect_constness) { return *this; } }; using Correct = BlockedRangeValue; using NonCopyable = BlockedRangeValue; using NonCopyAssignable = BlockedRangeValue; using NonDestructible = BlockedRangeValue; using NoOperatorLess = BlockedRangeValue; using OperatorLessNonConst = BlockedRangeValue; using WrongInputOperatorLess = BlockedRangeValue; using WrongReturnOperatorLess = BlockedRangeValue; using NoOperatorMinus = BlockedRangeValue; using OperatorMinusNonConst = BlockedRangeValue; using WrongInputOperatorMinus = BlockedRangeValue; using WrongReturnOperatorMinus = BlockedRangeValue; using NoOperatorPlus = BlockedRangeValue; using OperatorPlusNonConst = BlockedRangeValue; using WrongInputOperatorPlus = BlockedRangeValue; using WrongReturnOperatorPlus = BlockedRangeValue; } // namespace blocked_range_value namespace range { template struct Range { Range( Range&, tbb::split ) requires EnableSplitCtor {} Range( const Range& ) requires EnableCopyCtor = default; // Prospective destructors ~Range() requires EnableDtor = default; ~Range() = delete; bool empty() const requires (EnableEmpty == State::correct) { return true; } bool empty() requires (EnableEmpty == State::incorrect_constness) { return true; } Dummy empty() const requires (EnableEmpty == State::incorrect_return_type) { return Dummy{}; } bool is_divisible() const requires (EnableIsDivisible == State::correct) { return true; } bool is_divisible() requires (EnableIsDivisible == State::incorrect_constness) { return true; } Dummy is_divisible() const requires (EnableIsDivisible == State::incorrect_return_type) { return Dummy{}; } }; using Correct = Range; using NonCopyable = Range; using NonSplittable = Range; using NonDestructible = Range; using NoEmpty = Range; using EmptyNonConst = Range; using WrongReturnEmpty = Range; using NoIsDivisible = Range; using IsDivisibleNonConst = Range; using WrongReturnIsDivisible = Range; } // namespace range namespace parallel_for_body { template struct ParallelForBody { ParallelForBody( const ParallelForBody& ) requires EnableCopyCtor = default; // Prospective destructors ~ParallelForBody() requires EnableDtor = default; ~ParallelForBody() = delete; void operator()( Range& ) const requires (EnableFunctionCallOperator == State::correct) {} void operator()( Range& ) requires (EnableFunctionCallOperator == State::incorrect_constness) {} void operator()( Dummy ) const requires (EnableFunctionCallOperator == State::incorrect_first_input) {} }; template using Correct = ParallelForBody; template using NonCopyable = ParallelForBody; template using NonDestructible = ParallelForBody; template using NoOperatorRoundBrackets = ParallelForBody; template using OperatorRoundBracketsNonConst = ParallelForBody; template using WrongInputOperatorRoundBrackets = ParallelForBody; } // namespace parallel_for_body namespace parallel_for_function { template struct ParallelForFunc { void operator()( Index ) const requires (EnableFunctionCallOperator == State::correct) {} void operator()( Index ) requires (EnableFunctionCallOperator == State::incorrect_constness) {} void operator()( Dummy ) const requires (EnableFunctionCallOperator == State::incorrect_first_input) {} }; template using Correct = ParallelForFunc; template using NoOperatorRoundBrackets = ParallelForFunc; template using OperatorRoundBracketsNonConst = ParallelForFunc; template using WrongInputOperatorRoundBrackets = ParallelForFunc; } // namespace parallel_for_function namespace parallel_for_index { template struct ParallelForIndex { ParallelForIndex(int) requires EnableIntCtor {} ParallelForIndex( const ParallelForIndex& ) requires EnableCopyCtor = default; ParallelForIndex& operator=( const ParallelForIndex& ) requires EnableCopyAssign = default; // Prospective destructors ~ParallelForIndex() requires EnableDtor = default; ~ParallelForIndex() = delete; bool operator<( const ParallelForIndex& ) const requires (EnableLess == State::correct) { return true; } bool operator<( const ParallelForIndex& ) requires (EnableLess == State::incorrect_constness) { return true; } bool operator<( Dummy ) const requires (EnableLess == State::incorrect_first_input) { return true; } Dummy operator<( const ParallelForIndex& ) const requires (EnableLess == State::incorrect_return_type) { return Dummy{}; } std::size_t operator-( const ParallelForIndex& ) const requires (EnableMinus == State::correct) { return 0; } std::size_t operator-( const ParallelForIndex& ) requires (EnableMinus == State::incorrect_constness) { return 0; } std::size_t operator-( Dummy ) const requires (EnableMinus == State::incorrect_first_input) { return 0; } Dummy operator-( const ParallelForIndex& ) const requires (EnableMinus == State::incorrect_return_type) { return Dummy{}; } ParallelForIndex operator+( std::size_t ) const requires (EnablePlus == State::correct) { return *this; } ParallelForIndex operator+( std::size_t ) requires (EnablePlus == State::incorrect_constness) { return *this; } ParallelForIndex operator+( Dummy ) const requires (EnablePlus == State::incorrect_first_input) { return *this; } Dummy operator+( std::size_t ) const requires (EnablePlus == State::incorrect_return_type) { return Dummy{}; } }; using Correct = ParallelForIndex; using NoIntCtor = ParallelForIndex; using NonCopyable = ParallelForIndex; using NonCopyAssignable = ParallelForIndex; using NonDestructible = ParallelForIndex; using NoOperatorLess = ParallelForIndex; using OperatorLessNonConst = ParallelForIndex; using WrongInputOperatorLess = ParallelForIndex; using WrongReturnOperatorLess = ParallelForIndex; using NoOperatorMinus = ParallelForIndex; using OperatorMinusNonConst = ParallelForIndex; using WrongInputOperatorMinus = ParallelForIndex; using WrongReturnOperatorMinus = ParallelForIndex; using NoOperatorPlus = ParallelForIndex; using OperatorPlusNonConst = ParallelForIndex; using WrongInputOperatorPlus = ParallelForIndex; using WrongReturnOperatorPlus = ParallelForIndex; } // namespace parallel_for_index namespace parallel_for_each_body { template struct ParallelForEachBody { void operator()( const T& ) const requires (EnableFunctionCallOperator == State::correct) {} void operator()( const T& ) requires (EnableFunctionCallOperator == State::incorrect_constness) {} void operator()( Dummy ) const requires (EnableFunctionCallOperator == State::incorrect_first_input) {} }; template struct ParallelForEachFeederBody { void operator()( const T&, tbb::feeder& ) const requires (EnableFunctionCallOperator == State::correct) {} void operator()( const T&, tbb::feeder& ) requires (EnableFunctionCallOperator == State::incorrect_constness) {} void operator()( Dummy, tbb::feeder& ) const requires (EnableFunctionCallOperator == State::incorrect_first_input) {} void operator()( const T&, Dummy ) const requires (EnableFunctionCallOperator == State::incorrect_second_input) {} }; template using Correct = ParallelForEachBody; template using NoOperatorRoundBrackets = ParallelForEachBody; template using OperatorRoundBracketsNonConst = ParallelForEachBody; template using WrongInputOperatorRoundBrackets = ParallelForEachBody; template using WithFeeder = ParallelForEachFeederBody; template using WithFeederNoOperatorRoundBrackets = ParallelForEachFeederBody; template using WithFeederOperatorRoundBracketsNonConst = ParallelForEachFeederBody; template using WithFeederWrongFirstInputOperatorRoundBrackets = ParallelForEachFeederBody; template using WithFeederWrongSecondInputOperatorRoundBrackets = ParallelForEachFeederBody; } // namespace parallel_for_each_body namespace container_based_sequence { using iterator = int*; template struct ContainerBasedSequence { int* begin() requires EnableBegin { return nullptr; } int* end() requires EnableEnd { return nullptr; } }; using Correct = ContainerBasedSequence; using NoBegin = ContainerBasedSequence; using NoEnd = ContainerBasedSequence; struct ForwardIteratorCBS { utils::ForwardIterator begin() { return utils::ForwardIterator{}; } utils::ForwardIterator end() { return begin(); } }; } // namespace container_based_sequence namespace parallel_reduce_body { template struct ParallelReduceBody { ParallelReduceBody( ParallelReduceBody&, tbb::split ) requires EnableSplitCtor {} // Prospective destructors ~ParallelReduceBody() requires EnableDtor = default; ~ParallelReduceBody() = delete; void operator()( const Range& ) requires (EnableFunctionCallOperator == State::correct) {} void operator()( Dummy ) requires (EnableFunctionCallOperator == State::incorrect_first_input) {} void join( ParallelReduceBody& ) requires (EnableJoin == State::correct) {} void join( Dummy ) requires (EnableJoin == State::incorrect_first_input) {} }; template using Correct = ParallelReduceBody; template using NonSplittable = ParallelReduceBody; template using NonDestructible = ParallelReduceBody; template using NoOperatorRoundBrackets = ParallelReduceBody; template using WrongInputOperatorRoundBrackets = ParallelReduceBody; template using NoJoin = ParallelReduceBody; template using WrongInputJoin = ParallelReduceBody; } // namespace parallel_reduce_body namespace parallel_reduce_function { template struct ParallelReduceFunction { int operator()( const Range&, const int& ) const requires (EnableFunctionCallOperator == State::correct) { return 0; } int operator()( const Range&, const int& ) requires (EnableFunctionCallOperator == State::incorrect_constness) { return 0; } int operator()( Dummy, const int& ) const requires (EnableFunctionCallOperator == State::incorrect_first_input) { return 0; } int operator()( const Range&, Dummy ) const requires (EnableFunctionCallOperator == State::incorrect_second_input) { return 0; } Dummy operator()( const Range&, const int& ) const requires (EnableFunctionCallOperator == State::incorrect_return_type) { return Dummy{}; } }; template using Correct = ParallelReduceFunction; template using NoOperatorRoundBrackets = ParallelReduceFunction; template using OperatorRoundBracketsNonConst = ParallelReduceFunction; template using WrongFirstInputOperatorRoundBrackets = ParallelReduceFunction; template using WrongSecondInputOperatorRoundBrackets = ParallelReduceFunction; template using WrongReturnOperatorRoundBrackets = ParallelReduceFunction; } // namespace parallel_reduce_function namespace parallel_reduce_combine { template struct ParallelReduceCombine { T operator()( const T& a, const T& ) const requires (EnableFunctionCallOperator == State::correct) { return a; } T operator()( const T& a, const T& ) requires (EnableFunctionCallOperator == State::incorrect_constness) { return a; } T operator()( Dummy, const T& a ) const requires (EnableFunctionCallOperator == State::incorrect_first_input) { return a; } T operator()( const T& a, Dummy ) const requires (EnableFunctionCallOperator == State::incorrect_second_input) { return a; } Dummy operator()( const T&, const T& ) const requires (EnableFunctionCallOperator == State::incorrect_return_type) { return Dummy{}; } }; template using Correct = ParallelReduceCombine; template using NoOperatorRoundBrackets = ParallelReduceCombine; template using OperatorRoundBracketsNonConst = ParallelReduceCombine; template using WrongFirstInputOperatorRoundBrackets = ParallelReduceCombine; template using WrongSecondInputOperatorRoundBrackets = ParallelReduceCombine; template using WrongReturnOperatorRoundBrackets = ParallelReduceCombine; } // namespace parallel_reduce_reduction namespace parallel_scan_body { template struct ParallelScanBody { ParallelScanBody( ParallelScanBody&, tbb::split ) requires EnableSplitCtor {} void reverse_join( ParallelScanBody& ) requires (EnableReverseJoin == State::correct) {} void reverse_join( Dummy ) requires (EnableReverseJoin == State::incorrect_first_input) {} void assign( ParallelScanBody& ) requires (EnableAssign == State::correct) {} void assign( Dummy ) requires (EnableAssign == State::incorrect_first_input) {} void operator()( const Range&, tbb::pre_scan_tag ) requires (EnablePreScanRoundBrackets == State::correct) {} void operator()( Dummy, tbb::pre_scan_tag ) requires (EnablePreScanRoundBrackets == State::incorrect_first_input) {} void operator()( const Range&, Dummy ) requires (EnablePreScanRoundBrackets == State::incorrect_second_input) {} void operator()( const Range&, tbb::final_scan_tag ) requires (EnableFinalScanRoundBrackets == State::correct) {} void operator()( Dummy, tbb::final_scan_tag ) requires (EnableFinalScanRoundBrackets == State::incorrect_first_input) {} void operator()( const Range&, Dummy ) requires (EnableFinalScanRoundBrackets == State::incorrect_second_input) {} }; template using Correct = ParallelScanBody; template using NonSplittable = ParallelScanBody; template using NoReverseJoin = ParallelScanBody; template using WrongInputReverseJoin = ParallelScanBody; template using NoAssign = ParallelScanBody; template using WrongInputAssign = ParallelScanBody; template using NoPreScanOperatorRoundBrackets = ParallelScanBody; template using WrongFirstInputPreScanOperatorRoundBrackets = ParallelScanBody; template using WrongSecondInputPreScanOperatorRoundBrackets = ParallelScanBody; template using NoFinalScanOperatorRoundBrackets = ParallelScanBody; template using WrongFirstInputFinalScanOperatorRoundBrackets = ParallelScanBody; template using WrongSecondInputFinalScanOperatorRoundBrackets = ParallelScanBody; } // namespace parallel_scan_body namespace parallel_scan_function { template struct ParallelScanFunction { T operator()( const Range&, const T& a, bool ) const requires (EnableFunctionCallOperator == State::correct) { return a; } T operator()( const Range&, const T& a, bool ) requires (EnableFunctionCallOperator == State::incorrect_constness) { return a; } T operator()( Dummy, const T& a, bool ) const requires (EnableFunctionCallOperator == State::incorrect_first_input) { return a; } T operator()( const Range&, Dummy, bool ) const requires (EnableFunctionCallOperator == State::incorrect_second_input) { return T{}; } T operator()( const Range&, const T& a, Dummy ) const requires (EnableFunctionCallOperator == State::incorrect_third_input) { return a; } Dummy operator()( const Range&, const T& a, bool ) const requires (EnableFunctionCallOperator == State::incorrect_return_type) { return Dummy{}; } }; template using Correct = ParallelScanFunction; template using NoOperatorRoundBrackets = ParallelScanFunction; template using OperatorRoundBracketsNonConst = ParallelScanFunction; template using WrongFirstInputOperatorRoundBrackets = ParallelScanFunction; template using WrongSecondInputOperatorRoundBrackets = ParallelScanFunction; template using WrongThirdInputOperatorRoundBrackets = ParallelScanFunction; template using WrongReturnOperatorRoundBrackets = ParallelScanFunction; } // namespace parallel_scan_function namespace parallel_scan_combine { using namespace parallel_reduce_combine; } // namespace parallel_scan_combine namespace compare { template struct Compare { bool operator()( const T&, const T& ) const requires (EnableFunctionCallOperator == State::correct) { return true; } bool operator()( Dummy, const T& ) const requires (EnableFunctionCallOperator == State::incorrect_first_input) { return true; } bool operator()( const T&, Dummy ) const requires (EnableFunctionCallOperator == State::incorrect_second_input) { return true; } Dummy operator()( const T&, const T& ) const requires (EnableFunctionCallOperator == State::incorrect_return_type) { return Dummy{}; } }; template using Correct = Compare; template using NoOperatorRoundBrackets = Compare; template using WrongFirstInputOperatorRoundBrackets = Compare; template using WrongSecondInputOperatorRoundBrackets = Compare; template using WrongReturnOperatorRoundBrackets = Compare; } // namespace compare namespace hash_compare { template struct HashCompare { HashCompare( const HashCompare& ) requires EnableCopyCtor = default; // Prospective destructors ~HashCompare() requires EnableDtor = default; ~HashCompare() = delete; std::size_t hash( const Key& ) const requires (EnableHash == State::correct) { return 0; } std::size_t hash( const Key& ) requires (EnableHash == State::incorrect_constness) { return 0; } std::size_t hash( Dummy ) const requires (EnableHash == State::incorrect_first_input) { return 0; } Dummy hash( const Key& ) const requires (EnableHash == State::incorrect_return_type) { return Dummy{}; } bool equal( const Key&, const Key& ) const requires (EnableEqual == State::correct) { return true; } bool equal( const Key&, const Key& ) requires (EnableEqual == State::incorrect_constness) { return true; } bool equal( Dummy, const Key& ) const requires (EnableEqual == State::incorrect_first_input) { return true; } bool equal( const Key&, Dummy ) const requires (EnableEqual == State::incorrect_second_input) { return true; } Dummy equal( const Key&, const Key& ) const requires (EnableEqual == State::incorrect_return_type) { return Dummy{}; } }; template using Correct = HashCompare; template using NonCopyable = HashCompare; template using NonDestructible = HashCompare; template using NoHash = HashCompare; template using HashNonConst = HashCompare; template using WrongInputHash = HashCompare; template using WrongReturnHash = HashCompare; template using NoEqual = HashCompare; template using EqualNonConst = HashCompare; template using WrongFirstInputEqual = HashCompare; template using WrongSecondInputEqual = HashCompare; template using WrongReturnEqual = HashCompare; } // namespace hash_compare namespace rw_mutex { template struct DefineRWScopedLock { struct scoped_lock { scoped_lock() requires EnableSLDefaultCtor = default; scoped_lock( RwMutex&, bool = true ) requires EnableSLMutexCtor {} // Prospective destructors ~scoped_lock() requires EnableSLDtor = default; ~scoped_lock() = delete; void acquire( RwMutex&, bool = true ) requires (EnableSLAcquire == State::correct) {} void acquire( Dummy, bool = true ) requires (EnableSLAcquire == State::incorrect_first_input) {} void acquire( RwMutex&, Dummy = Dummy{} ) requires (EnableSLAcquire == State::incorrect_second_input) {} bool try_acquire( RwMutex&, bool = true ) requires (EnableSLTryAcquire == State::correct) { return true; } bool try_acquire( Dummy, bool = true ) requires (EnableSLTryAcquire == State::incorrect_first_input) { return true; } bool try_acquire( RwMutex&, Dummy = Dummy{} ) requires (EnableSLTryAcquire == State::incorrect_second_input) { return true; } Dummy try_acquire( RwMutex&, bool = true ) requires (EnableSLTryAcquire == State::incorrect_return_type) { return Dummy{}; } void release() requires (EnableSLRelease) {} bool upgrade_to_writer() requires (EnableSLUpgrade == State::correct) { return true; } Dummy upgrade_to_writer() requires (EnableSLUpgrade == State::incorrect_return_type) { return Dummy{}; } bool downgrade_to_reader() requires (EnableSLDowngrade == State::correct) { return true; } Dummy downgrade_to_reader() requires (EnableSLDowngrade == State::incorrect_return_type) { return Dummy{}; } bool is_writer() const requires (EnableIsWriter == State::correct) { return true; } Dummy is_writer() const requires (EnableIsWriter == State::incorrect_return_type) { return Dummy{}; } bool is_writer() requires (EnableIsWriter == State::incorrect_constness) { return true; } }; }; template inline const bool mutex_trait_impl = true; template <> inline const int mutex_trait_impl = 0; template <> inline bool mutex_trait_impl = true; template struct RWMutex : std::conditional_t, EnableSLDefaultCtor, EnableSLMutexCtor, EnableSLDtor, EnableSLAcquire, EnableSLTryAcquire, EnableSLRelease, EnableSLUpgrade, EnableSLDowngrade, EnableSLIsWriter>, Dummy> {}; using Correct = RWMutex; using NoScopedLock = RWMutex; using ScopedLockNoDefaultCtor = RWMutex; using ScopedLockNoMutexCtor = RWMutex; using ScopedLockNoDtor = RWMutex; using ScopedLockNoAcquire = RWMutex; using ScopedLockWrongFirstInputAcquire = RWMutex; using ScopedLockWrongSecondInputAcquire = RWMutex; using ScopedLockNoTryAcquire = RWMutex; using ScopedLockWrongFirstInputTryAcquire = RWMutex; using ScopedLockWrongSecondInputTryAcquire = RWMutex; using ScopedLockWrongReturnTryAcquire = RWMutex; using ScopedLockNoRelease = RWMutex; using ScopedLockNoUpgrade = RWMutex; using ScopedLockWrongReturnUpgrade = RWMutex; using ScopedLockNoDowngrade = RWMutex; using ScopedLockWrongReturnDowngrade = RWMutex; using ScopedLockNoIsWriter = RWMutex; using ScopedLockIsWriterNonConst = RWMutex; using ScopedLockWrongReturnIsWriter = RWMutex; } // namespace rw_mutex // Flow Graph testing infrastructure below namespace input_node_body { template struct InputNodeBody { InputNodeBody( const InputNodeBody& ) requires EnableCopyCtor = default; // Prospective destructors ~InputNodeBody() requires EnableDtor = default; ~InputNodeBody() = delete; Output operator()( tbb::flow_control& ) requires (EnableFunctionCallOperator == State::correct) { return Output{}; } Output operator()( Dummy ) requires (EnableFunctionCallOperator == State::incorrect_first_input) { return Output{}; } Dummy operator()( tbb::flow_control& ) requires (EnableFunctionCallOperator == State::incorrect_return_type) { return Dummy{}; } }; template using Correct = InputNodeBody; template using NonCopyable = InputNodeBody; template using NonDestructible = InputNodeBody; template using NoOperatorRoundBrackets = InputNodeBody; template using WrongInputOperatorRoundBrackets = InputNodeBody; template using WrongReturnOperatorRoundBrackets = InputNodeBody; } // namespace input_node_body namespace function_node_body { template struct FunctionNodeBody { FunctionNodeBody( const FunctionNodeBody& ) requires EnableCopyCtor = default; // Prospective destructors ~FunctionNodeBody() requires EnableDtor = default; ~FunctionNodeBody() = delete; Output operator()( const Input& ) requires (EnableFunctionCallOperator == State::correct) { return Output{}; } Output operator()( Dummy ) requires (EnableFunctionCallOperator == State::incorrect_first_input) { return Dummy{}; } Dummy operator()( const Input& ) requires (EnableFunctionCallOperator == State::incorrect_return_type) { return Output{}; } }; template using Correct = FunctionNodeBody; template using NonCopyable = FunctionNodeBody; template using NonDestructible = FunctionNodeBody; template using NoOperatorRoundBrackets = FunctionNodeBody; template using WrongInputRoundBrackets = FunctionNodeBody; template using WrongReturnRoundBrackets = FunctionNodeBody; } // namespace function_node_body namespace mf_async_node_body { template struct PortsNodeBody { PortsNodeBody( const PortsNodeBody& ) requires EnableCopyCtor = default; // Prospective destructors ~PortsNodeBody() requires EnableDtor = default; ~PortsNodeBody() = delete; void operator()( const Input&, PortsType& ) requires (EnableFunctionCallOperator == State::correct) {} void operator()( Dummy, PortsType& ) requires (EnableFunctionCallOperator == State::incorrect_first_input) {} void operator()( const Input&, Dummy ) requires (EnableFunctionCallOperator == State::incorrect_second_input) {} }; } // namespace mf_async_node_body namespace multifunction_node_body { template using output_ports_type = typename tbb::flow::multifunction_node::output_ports_type; using mf_async_node_body::PortsNodeBody; template using Correct = PortsNodeBody, /*CopyCtor = */true, /*Dtor = */true, /*() = */State::correct>; template using NonCopyable = PortsNodeBody, /*CopyCtor = */false, /*Dtor = */true, /*() = */State::correct>; template using NonDestructible = PortsNodeBody, /*CopyCtor = */true, /*Dtor = */false, /*() = */State::correct>; template using NoOperatorRoundBrackets = PortsNodeBody, /*CopyCtor = */true, /*Dtor = */true, /*() = */State::not_defined>; template using WrongFirstInputOperatorRoundBrackets = PortsNodeBody, /*CopyCtor = */true, /*Dtor = */true, /*() = */State::incorrect_first_input>; template using WrongSecondInputOperatorRoundBrackets = PortsNodeBody, /*CopyCtor = */true, /*Dtor = */true, /*() = */State::incorrect_second_input>; } // namespace multifunction_node_body namespace async_node_body { template using gateway_type = typename tbb::flow::async_node::gateway_type; using mf_async_node_body::PortsNodeBody; template using Correct = PortsNodeBody, /*CopyCtor = */true, /*Dtor = */true, /*() = */State::correct>; template using NonCopyable = PortsNodeBody, /*CopyCtor = */false, /*Dtor = */true, /*() = */State::correct>; template using NonDestructible = PortsNodeBody, /*CopyCtor = */true, /*Dtor = */false, /*() = */State::correct>; template using NoOperatorRoundBrackets = PortsNodeBody, /*CopyCtor = */true, /*Dtor = */true, /*() = */State::not_defined>; template using WrongFirstInputOperatorRoundBrackets = PortsNodeBody, /*CopyCtor = */true, /*Dtor = */true, /*() = */State::incorrect_first_input>; template using WrongSecondInputOperatorRoundBrackets = PortsNodeBody, /*CopyCtor = */true, /*Dtor = */true, /*() = */State::incorrect_second_input>; } // namespace async_node_body namespace continue_node_body { template struct ContinueNodeBody { ContinueNodeBody( const ContinueNodeBody& ) requires EnableCopyCtor = default; // Prospective destructors ~ContinueNodeBody() requires EnableDtor = default; ~ContinueNodeBody() = delete; Output operator()( tbb::flow::continue_msg ) requires (EnableFunctionCallOperator == State::correct) { return Output{}; } Output operator()( Dummy ) requires (EnableFunctionCallOperator == State::incorrect_first_input) { return Output{}; } Dummy operator()( tbb::flow::continue_msg ) requires (EnableFunctionCallOperator == State::incorrect_return_type) { return Dummy{}; } }; template using Correct = ContinueNodeBody; template using NonCopyable = ContinueNodeBody; template using NonDestructible = ContinueNodeBody; template using NoOperatorRoundBrackets = ContinueNodeBody; template using WrongInputOperatorRoundBrackets = ContinueNodeBody; template using WrongReturnOperatorRoundBrackets = ContinueNodeBody; } // namespace continue_node_body namespace sequencer { template struct Sequencer { Sequencer( const Sequencer& ) requires EnableCopyCtor = default; // Prospective destructors ~Sequencer() requires EnableDtor = default; ~Sequencer() = delete; std::size_t operator()( const T& ) requires (EnableFunctionCallOperator == State::correct) { return 0; } std::size_t operator()( Dummy ) requires (EnableFunctionCallOperator == State::incorrect_first_input) { return 0; } Dummy operator()( const T& ) requires (EnableFunctionCallOperator == State::incorrect_return_type) { return Dummy{}; } }; template using Correct = Sequencer; template using NonCopyable = Sequencer; template using NonDestructible = Sequencer; template using NoOperatorRoundBrackets = Sequencer; template using WrongInputOperatorRoundBrackets = Sequencer; template using WrongReturnOperatorRoundBrackets = Sequencer; } // namespace sequencer namespace join_node_function_object { template struct JoinNodeFunctionObject { JoinNodeFunctionObject( const JoinNodeFunctionObject& ) requires EnableCopyCtor = default; // Prospective destructors ~JoinNodeFunctionObject() requires EnableDtor = default; ~JoinNodeFunctionObject() = delete; Key operator()( const Input& ) requires (EnableFunctionCallOperator == State::correct) { return Key{}; } Key operator()( Dummy ) requires (EnableFunctionCallOperator == State::incorrect_first_input) { return Key{}; } Dummy operator()( const Input& ) requires (EnableFunctionCallOperator == State::incorrect_return_type) { return Dummy{}; } }; template using Correct = JoinNodeFunctionObject; template using NonCopyable = JoinNodeFunctionObject; template using NonDestructible = JoinNodeFunctionObject; template using NoOperatorRoundBrackets = JoinNodeFunctionObject; template using WrongInputOperatorRoundBrackets = JoinNodeFunctionObject; template using WrongReturnOperatorRoundBrackets = JoinNodeFunctionObject; } // namespace join_node_function_object template concept container_range = tbb::detail::tbb_range && std::input_iterator && requires(T& range) { typename T::value_type; typename T::reference; typename T::size_type; typename T::difference_type; { range.begin() } -> std::same_as; { range.end() } -> std::same_as; { std::as_const(range).grainsize() } -> std::same_as; }; } // namespace test_concepts #endif // __TBB_CPP20_CONCEPTS_PRESENT #endif // __TBB_test_common_concepts_common_H