Repository: duckdb/duckdb
File: src/include/duckdb/common/primitive_dictionary.hpp (C++)

Code before:
	      dictionary(reinterpret_cast<primitive_dictionary_entry_t *>(allocated_dictionary.get())), full(false) {
		// Initialize empty
		for (idx_t i = 0; i < capacity; i++) {
			dictionary[i].index = INVALID_INDEX;
		}
	}

public:
	//! Insert value into dictionary (if not full)
	void Insert(SRC value) {
		if (full) {
			return;
		}
		auto &entry = Lookup(value);
		if (entry.IsEmpty()) {
			if (size + 1 > maximum_size || !AddToTarget(value)) {
				full = true;
				return;
			}
			entry.value = value;
			entry.index = size++;
		}
	}

	//! Insert value into dictionary without calling AddToTarget()
	void InsertRaw(SRC value) {
		if (full) {
			return;
		}
		auto &entry = Lookup(value);
		if (entry.IsEmpty()) {
			if (size + 1 > maximum_size) {
				full = true;
				return;
			}
			entry.value = value;
			entry.index = size++;
		}
	}

	//! Get dictionary index of an already inserted value
	uint32_t GetIndex(const SRC &value) const {
		const auto &entry = Lookup(value);
		D_ASSERT(!entry.IsEmpty());
		return entry.index;
	}

	//! Iterates over inserted values
	template <typename U = SRC, typename std::enable_if<!std::is_same<U, string_t>::value, int>::type = 0>
	void IterateValues(const std::function<void(const SRC &, const TGT &)> &fun) const {
		const auto target_values = reinterpret_cast<const TGT *>(allocated_target.get());

Review comment (suggestion):
Instead of duplicating this function, could we add a template to the `Insert` function?

```c++
	template <bool ADD_TO_TARGET = false>
	void Insert(SRC value) {
		if (full) {
			return;
		}
		auto &entry = Lookup(value);
		if (entry.IsEmpty()) {
			if (size + 1 > maximum_size || (ADD_TO_TARGET && !AddToTarget(value))) {
				full = true;
				return;
			}
			entry.value = value;
			entry.index = size++;
		}
	}
```

Then you can use `Insert<false>` instead of `InsertRaw`.

Code after:
	    : allocator(allocator_p), maximum_size(maximum_size_p), size(0),
	      capacity(NextPowerOfTwo(maximum_size * LOAD_FACTOR)), capacity_mask(capacity - 1),
	      maximum_target_capacity(maximum_target_capacity_p),
	      allocated_dictionary(allocator.Allocate(capacity * sizeof(primitive_dictionary_entry_t))),
	      allocated_target(allocator.Allocate(std::is_same<TGT, string_t>::value
	                                              ? MinValue(INITIAL_TARGET_CAPACITY, maximum_target_capacity)
	                                              : capacity * sizeof(TGT))),
	      target_stream(allocated_target.get(), allocated_target.GetSize()),
	      dictionary(reinterpret_cast<primitive_dictionary_entry_t *>(allocated_dictionary.get())), full(false) {
		Clear();
	}

public:
	//! Insert value into dictionary (if not full)
	template <bool ADD_TO_TARGET = false>
	void Insert(SRC value) {
		if (full) {
			return;
		}
		auto &entry = Lookup(value);
		if (entry.IsEmpty()) {
			if (size + 1 > maximum_size || (ADD_TO_TARGET && !AddToTarget(value))) {
				full = true;
				return;
			}
			entry.value = value;
			entry.index = size++;
		}
	}

	//! Get dictionary index of an already inserted value
	uint32_t GetIndex(const SRC &value) const {
		const auto &entry = Lookup(value);
		D_ASSERT(!entry.IsEmpty());
		return entry.index;
	}

	//! Iterates over inserted values
	template <typename U = SRC, typename std::enable_if<!std::is_same<U, string_t>::value, int>::type = 0>
	void IterateValues(const std::function<void(const SRC &, const TGT &)> &fun) const {
		const auto target_values = reinterpret_cast<const TGT *>(allocated_target.get());
		for (idx_t i = 0; i < capacity; i++) {
			auto &entry = dictionary[i];
			if (entry.IsEmpty()) {
				continue;
			}
			fun(entry.value, target_values[entry.index]);
		}
	}

	//! Specialized template to iterate over string_t values