3434#include < map>
3535#include < memory>
3636#include < stack>
37+ #include < numeric>
3738#include < type_traits>
3839#include < unordered_map>
3940#include < utility>
@@ -1117,12 +1118,11 @@ static ParsedType parseType(const Token* tok,
11171118 type.nameStart = start;
11181119 type.nameEnd = last;
11191120 if (templateParams && start == last) {
1120- for (std::size_t i = 0 ; i < templateParams->size (); ++i) {
1121- if ((*templateParams)[i]->str () == start->str ()) {
1122- result.templateParamIndex = static_cast <int >(i);
1123- break ;
1124- }
1125- }
1121+ const auto it = std::find_if (templateParams->cbegin (), templateParams->cend (), [&](const Token* templateParam) {
1122+ return templateParam->str () == start->str ();
1123+ });
1124+ if (it != templateParams->cend ())
1125+ result.templateParamIndex = static_cast <int >(it - templateParams->cbegin ());
11261126 }
11271127 } else
11281128 return ParsedType ();
@@ -1241,8 +1241,7 @@ static std::vector<DeducedToken> renderDeducedType(const ExprType& type, bool ke
12411241 break ;
12421242 }
12431243 }
1244- for (int i = 0 ; i < type.pointer ; ++i)
1245- tokens.emplace_back (" *" );
1244+ tokens.insert (tokens.end (), type.pointer , DeducedToken (" *" ));
12461245 if (type.pointer > 0 && keepTopConst && type.topConst )
12471246 tokens.emplace_back (" const" );
12481247 return tokens;
@@ -1660,10 +1659,43 @@ static ExprType parseOperandType(const DeductionContext& ctx, const Token*& tok,
16601659 return type;
16611660}
16621661
1662+ static bool isArithmeticOp (const std::string& s)
1663+ {
1664+ return s == " +" || s == " -" || s == " *" || s == " /" || s == " %" ;
1665+ }
1666+
1667+ static bool isComparisonOp (const std::string& s)
1668+ {
1669+ return s == " ==" || s == " !=" || s == " <=" || s == " >=" || s == " &&" || s == " ||" ;
1670+ }
1671+
1672+ static bool isBitOp (const std::string& s)
1673+ {
1674+ return s == " &" || s == " |" || s == " ^" ;
1675+ }
1676+
1677+ static bool isShiftOp (const std::string& s)
1678+ {
1679+ return s == " <<" || s == " >>" ;
1680+ }
1681+
16631682static bool isSupportedBinaryOp (const std::string& s)
16641683{
1665- return s == " +" || s == " -" || s == " *" || s == " /" || s == " %" || s == " &" || s == " |" || s == " ^" || s == " <<" ||
1666- s == " >>" || s == " ==" || s == " !=" || s == " <=" || s == " >=" || s == " &&" || s == " ||" ;
1684+ return isArithmeticOp (s) || isComparisonOp (s) || isBitOp (s) || isShiftOp (s);
1685+ }
1686+
1687+ static bool isPointerType (const ExprType& type)
1688+ {
1689+ return type.pointer > 0 ;
1690+ }
1691+
1692+ // fold |operands| with the usual arithmetic conversions
1693+ static ExprType convertArithmeticTypes (const Settings& settings, std::vector<ExprType>::const_iterator begin,
1694+ std::vector<ExprType>::const_iterator end, const ExprType& first)
1695+ {
1696+ return std::accumulate (begin, end, first, [&](const ExprType& lhs, const ExprType& rhs) {
1697+ return usualArithmeticConversion (settings, lhs, rhs);
1698+ });
16671699}
16681700
16691701// Determine the type of the expression [start, end). This is a flat scan:
@@ -1696,22 +1728,10 @@ static ExprType evalExpressionType(const DeductionContext& ctx, const Token* sta
16961728 if (ops.empty ())
16971729 return operands[0 ];
16981730
1699- bool hasCmp = false ;
1700- bool hasBit = false ;
1701- bool hasShift = false ;
1702- std::size_t firstShift = ops.size ();
1703- for (std::size_t i = 0 ; i < ops.size (); ++i) {
1704- const std::string& s = ops[i];
1705- if (s == " ==" || s == " !=" || s == " <=" || s == " >=" || s == " &&" || s == " ||" )
1706- hasCmp = true ;
1707- else if (s == " &" || s == " |" || s == " ^" )
1708- hasBit = true ;
1709- else if (s == " <<" || s == " >>" ) {
1710- hasShift = true ;
1711- if (firstShift == ops.size ())
1712- firstShift = i;
1713- }
1714- }
1731+ const bool hasCmp = std::any_of (ops.cbegin (), ops.cend (), isComparisonOp);
1732+ const bool hasBit = std::any_of (ops.cbegin (), ops.cend (), isBitOp);
1733+ const auto firstShift = std::find_if (ops.cbegin (), ops.cend (), isShiftOp);
1734+ const bool hasShift = firstShift != ops.cend ();
17151735 // the grouping of the operators must not influence the result type
17161736 if (hasCmp && (hasBit || hasShift))
17171737 return ExprType ();
@@ -1722,28 +1742,26 @@ static ExprType evalExpressionType(const DeductionContext& ctx, const Token* sta
17221742 return result;
17231743 }
17241744
1745+ // class types (operator overloads) are not supported
1746+ if (std::any_of (operands.cbegin (), operands.cend (), [](const ExprType& operand) {
1747+ return operand.pointer == 0 && !operand.isArithmetic ();
1748+ }))
1749+ return ExprType ();
1750+
17251751 // pointer arithmetic
1726- std::size_t pointerCount = 0 ;
1727- std::size_t pointerIndex = 0 ;
1728- for (std::size_t i = 0 ; i < operands.size (); ++i) {
1729- if (operands[i].pointer > 0 ) {
1730- ++pointerCount;
1731- pointerIndex = i;
1732- } else if (!operands[i].isArithmetic ())
1733- return ExprType (); // class types (operator overloads) are not supported
1734- }
1752+ const std::size_t pointerCount = std::count_if (operands.cbegin (), operands.cend (), isPointerType);
17351753 if (pointerCount > 1 )
17361754 return ExprType ();
17371755 if (pointerCount == 1 ) {
17381756 if (std::any_of (ops.cbegin (), ops.cend (), [](const std::string& s) {
17391757 return s != " +" && s != " -" ;
17401758 }))
17411759 return ExprType ();
1742- for ( std::size_t i = 0 ; i < operands.size (); ++i ) {
1743- if (i != pointerIndex && !operands[i] .isIntegral ())
1744- return ExprType ();
1745- }
1746- ExprType result = operands[pointerIndex] ;
1760+ if (! std::all_of (operands. cbegin (), operands.cend (), []( const ExprType& operand ) {
1761+ return operand. pointer > 0 || operand .isIntegral ();
1762+ }))
1763+ return ExprType ();
1764+ ExprType result = * std::find_if ( operands. cbegin (), operands. cend (), isPointerType) ;
17471765 result.topConst = false ;
17481766 result.fromArray = false ;
17491767 return result;
@@ -1754,24 +1772,16 @@ static ExprType evalExpressionType(const DeductionContext& ctx, const Token* sta
17541772 return ExprType ();
17551773 // the result is the promoted type of the sub expression left of the
17561774 // first shift operator
1757- ExprType result = operands[0 ];
1758- for (std::size_t i = 1 ; i <= firstShift; ++i) {
1759- result = usualArithmeticConversion (*ctx.settings , result, operands[i]);
1760- if (!result.valid )
1761- return ExprType ();
1762- }
1763- return promoteType (*ctx.settings , result);
1775+ const std::size_t leftOfShift = firstShift - ops.cbegin ();
1776+ const ExprType result = convertArithmeticTypes (*ctx.settings , operands.cbegin () + 1 ,
1777+ operands.cbegin () + 1 + leftOfShift, operands[0 ]);
1778+ return result.valid ? promoteType (*ctx.settings , result) : ExprType ();
17641779 }
17651780
17661781 if (hasBit && !std::all_of (operands.cbegin (), operands.cend (), isIntegralType))
17671782 return ExprType ();
17681783
1769- ExprType result = operands[0 ];
1770- for (std::size_t i = 1 ; i < operands.size (); ++i) {
1771- result = usualArithmeticConversion (*ctx.settings , result, operands[i]);
1772- if (!result.valid )
1773- return ExprType ();
1774- }
1784+ ExprType result = convertArithmeticTypes (*ctx.settings , operands.cbegin () + 1 , operands.cend (), operands[0 ]);
17751785 result.fromArray = false ;
17761786 return result;
17771787}
@@ -1959,23 +1969,21 @@ static void deduceTemplateArgumentsAtFunctionCall(const DeductionContext& ctx,
19591969 if (matches.size () > 1 ) {
19601970 // identical deductions are interchangeable; otherwise the unique
19611971 // candidate with the most exact matches wins, or nothing is deduced
1962- bool identical = true ;
1963- for (std:: size_t i = 1 ; i < matches. size () && identical; ++i)
1964- identical = (matches[i]. deduced == matches[ 0 ]. deduced );
1972+ const bool identical = std::all_of (matches. cbegin () + 1 , matches. cend (), [&]( const Candidate& match) {
1973+ return match. deduced == matches[ 0 ]. deduced ;
1974+ } );
19651975 if (!identical) {
19661976 const int maxExact =
19671977 std::max_element (matches.cbegin (), matches.cend (), [](const Candidate& lhs, const Candidate& rhs) {
19681978 return lhs.exactMatches < rhs.exactMatches ;
19691979 })->exactMatches ;
1970- std::size_t numberOfBest = 0 ;
1971- for (std::size_t i = 0 ; i < matches.size (); ++i) {
1972- if (matches[i].exactMatches == maxExact) {
1973- ++numberOfBest;
1974- winner = i;
1975- }
1976- }
1977- if (numberOfBest != 1 )
1980+ if (std::count_if (matches.cbegin (), matches.cend (), [&](const Candidate& match) {
1981+ return match.exactMatches == maxExact;
1982+ }) != 1 )
19781983 return ;
1984+ winner = std::find_if (matches.cbegin (), matches.cend (), [&](const Candidate& match) {
1985+ return match.exactMatches == maxExact;
1986+ }) - matches.cbegin ();
19791987 }
19801988 }
19811989
0 commit comments