example1() {
[ $# -eq 0 ] && return
echo "$1"
shift
example1 "$@"
}
example2() {
for arg in "$@"; do
echo "$arg"
done
}
touch 1 "2 3" 4
example1 *
example2 *
# both examples print:
# 1
# 2 3
# 4 template<typename Container>
void foo1(Container const& c);
template<typename Iterator>
void foo2(Iterator first);
template<typename Iterator>
void foo3(Iterator first, Iterator last);
template<typename Iterator>
void foo4(Iterator first, std::size_t num);
template<typename T>
void foo5(std::vector<T> const& vec);
void foo6(char const* const* first, std::size_t num);
foo6 is a pretty good alternative here, imo: std::vector<char*> vec(...);
foo6(&vec.front(), vec.size());
It would be cool if the compiler could figure templated type conversion out, but the crux of the issue is, as I understand it, that T<A> and T<A const> are not necessarily implemented the same way. std::vector<char*> vec1(...);
std::vector<char const*> vec2(...);
std::copy(vec1.begin(), vec1.end(), vec2.begin()); // works (1)
std::copy(vec2.begin(), vec2.end(), vec1.begin()); // fails (2)
If this compiled, the second example would invoke undefined behavior and crash if you attempted to write to an element that pointed to read-only memory (e.g., a string literal). Iterator find(T const& value) const;
The const actually _helps_ callers: find accepts both const and non-const references. A non-const argument will be implicitly cast to const by the compiler. Iterator find(T& value) const;
This function signature accepts only non-const references (unless T is const). A caller must const_cast a const argument to use it (bad). T& front();
T const& front() const;
But "auto" makes the code shorter when the return type is const or unknown: auto& v = c.front(); // overload is deduced by the compiler based on the constness of c.
Basically, invoking "operator delete" on a pointer to an incomplete type (aka opaque pointer) is usually undefined. Calling "operator new" on an incomplete type is not possible (because its size is 0). Since unique_ptr deals with allocation/deallocation, and doesn't just copy pointer values around, it's not fully comparable to a plain pointer.
nice_byte proposed a good solution: if you can, abstract the new/delete logic to another file, in which the complete type of "Gadget" is known.