François Andrieux gave me a good workaround for this Visual Studio 2017 problem. I was trying to build on his answer like so:
template<class T, size_t N>
ostream& vector_insert_impl(ostream& lhs, const char*, const T& rhs)
{
return lhs << at(rhs, N);
}
template<class T, size_t N, size_t... I>
ostream& vector_insert_impl(ostream& lhs, const char* delim, const T& rhs)
{
return vector_insert_impl<T, I...>(lhs << at(rhs, N) << delim, delim, rhs);
}
template <typename T, size_t... I>
ostream& vector_insert(ostream& lhs, const char* delim, const T& rhs, index_sequence<I...>)
{
return vector_insert_impl<T, I...>(it, delim, rhs);
}
The key difference is that the "end of recursion" templated function actually inserts the last value into the ostream
, and not the delimiter rather than being a no-op. But when I try to compile this I get the error:
error C2668:
vector_insert_impl
: ambiguous call to overloaded function (compiling source file ....\src\STETestbed\Test.cpp)
note: could bestd::ostream &vector_insert_impl<T,2,>(std::ostream &,const char *,const T &)
note: orstd::ostream &vector_insert_impl<T,2>(std::ostream &,const char *,const T &)
I thought variable length template functions were considered 3rd class citizens and fixed length template functions would always be preferred. That preference doesn't appear to be in effect here. Is there a workaround which will force the compiler to choose my "end of recursion" function enabling me to avoid inserting the delimiter?
Is there a workaround which will force the compiler to choose my "end of recursion" function enabling me to avoid inserting the delimiter?
You can add the "Next
" element
template <typename T, std::size_t N>
std::ostream & vector_insert_impl (std::ostream & lhs, char const *, T const & rhs)
{
return lhs << at(rhs, N);
}
// ..................................vvvvvvvvvvvvvvvv
template <typename T, std::size_t N, std::size_t Next, std::size_t ... I>
std::ostream & vector_insert_impl (std::ostream & lhs, char const * delim, T const & rhs)
{ // ............................vvvv
return vector_insert_impl<T, Next, I...>(lhs << at(rhs, N) << delim, delim, rhs);
}
but, if you can use C++17, I suppose if constexpr
is a better solution
template <typename T, std::size_t N, std::size_t ... Is>
std::ostream & vector_insert_impl (std::ostream & lhs, char const * delim, T const & rhs)
{
if constexpr ( sizeof...(Is) )
return vector_insert_impl<T, Is...>(lhs << at(rhs, N) << delim, delim, rhs);
else
return lhs << at(rhs, N);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With