nit: for non-trivial functions, I think it helps to narrow down T instead of having to deduct it from its callsites and usage.
What do you think about adding an IsCoinRef concept, and adding std::span to the function signature?
<details>
<summary>git diff on 76a8f22c5c</summary>
diff --git a/src/consensus/tx_verify.cpp b/src/consensus/tx_verify.cpp
index 97f8241089..ab27387cc4 100644
--- a/src/consensus/tx_verify.cpp
+++ b/src/consensus/tx_verify.cpp
@@ -14,6 +14,8 @@
#include <util/check.h>
#include <util/moneystr.h>
+#include <span>
+
template <typename T>
static constexpr const Coin& GetCoin(const T& item)
{
@@ -158,8 +160,8 @@ template unsigned int GetP2SHSigOpCount<std::span<const Coin>>(
template unsigned int GetP2SHSigOpCount<std::span<std::reference_wrapper<const Coin>>>(
const CTransaction& tx, const std::span<std::reference_wrapper<const Coin>>);
-template <typename T>
-int64_t GetTransactionSigOpCost(const CTransaction& tx, const T coins, uint32_t flags)
+template<IsCoinRef CoinRef>
+int64_t GetTransactionSigOpCost(const CTransaction& tx, std::span<CoinRef> coins, uint32_t flags)
{
int64_t nSigOps = GetLegacySigOpCount(tx) * WITNESS_SCALE_FACTOR;
@@ -172,18 +174,18 @@ int64_t GetTransactionSigOpCost(const CTransaction& tx, const T coins, uint32_t
Assert(coins.size() == tx.vin.size());
auto input_it = tx.vin.begin();
- for (auto it = coins.begin(); it != coins.end(); ++it, ++input_it) {
- const Coin& coin{GetCoin(*it)};
+ for (const Coin& coin : coins) {
assert(!coin.IsSpent());
const CTxOut &prevout = coin.out;
nSigOps += CountWitnessSigOps(input_it->scriptSig, prevout.scriptPubKey, &input_it->scriptWitness, flags);
+ ++input_it;
}
return nSigOps;
}
-template int64_t GetTransactionSigOpCost<std::span<const Coin>>(
+template int64_t GetTransactionSigOpCost<const Coin>(
const CTransaction& tx, std::span<const Coin> coins, uint32_t flags);
-template int64_t GetTransactionSigOpCost<std::span<std::reference_wrapper<const Coin>>>(
+template int64_t GetTransactionSigOpCost<std::reference_wrapper<const Coin>>(
const CTransaction& tx, const std::span<std::reference_wrapper<const Coin>> coins, uint32_t flags);
template <typename T>
diff --git a/src/consensus/tx_verify.h b/src/consensus/tx_verify.h
index 88b2d6164b..b8ab114306 100644
--- a/src/consensus/tx_verify.h
+++ b/src/consensus/tx_verify.h
@@ -48,6 +48,8 @@ unsigned int GetLegacySigOpCount(const CTransaction& tx);
template <typename T>
unsigned int GetP2SHSigOpCount(const CTransaction& tx, const T coins);
+template<typename T>
+concept IsCoinRef = std::convertible_to<T, const Coin&>;
/**
* Compute total signature operation cost of a transaction.
* [@param](/bitcoin-bitcoin/contributor/param/)[in] tx Transaction for which we are computing the cost
@@ -55,8 +57,8 @@ unsigned int GetP2SHSigOpCount(const CTransaction& tx, const T coins);
* [@param](/bitcoin-bitcoin/contributor/param/)[in] flags Script verification flags
* [@return](/bitcoin-bitcoin/contributor/return/) Total signature operation cost of tx
*/
-template <typename T>
-int64_t GetTransactionSigOpCost(const CTransaction& tx, const T coins, uint32_t flags);
+template<IsCoinRef CoinRef>
+int64_t GetTransactionSigOpCost(const CTransaction& tx, std::span<CoinRef> coins, uint32_t flags);
/**
* Check if transaction is final and can be included in a block with the
</details>
(the same applies for GetLegacySigOpCount and GetP2SHSigOpCount)
edit: I see this is already (partially) suggested and addressed in #32317 (review), I think adding the IsCoinRef concept could still be nice but less important than specifying the std::span