Currently, I have a function template like this that converts a vector
into a string
(just a natural string, separating the elements with a comma):
//the type T must be passable into std::to_string
template<typename T>
std::string vec_to_str(const std::vector<T> &vec);
As you can see, this is only meant for vectors whose elements can be passed into the built-in std::to_string
function (such as int
, double
, etc.)
Is it considered a good practice to document with comments the allowed T
? If not, what should I do? Is it possible to enforce this in a better way?
A template is a document type that creates a copy of itself when you open it. For example, a business plan is a common document that is written in Word. Instead of creating the structure of the business plan from scratch, you can use a template with predefined page layout, fonts, margins, and styles.
Template methods call the following kinds of operations: concrete operations (either on the ConcreteClass or on client classes); concrete AbstractClass operations (i.e., operations that are generally useful to subclasses); primitive operations (i.e., abstract operations);
Word templates come ready-to-use with pre-set themes and styles. All you need to do is add your content. Each time you start Word, you can choose a template from the gallery, click a category to see more templates, or search for more templates online. For a closer look at any template, click it to open a large preview.
With static_assert
and some expression SFINAE, you can have a nice compile time error message:
template<typename T>
constexpr auto allowed(int) -> decltype(std::to_string(std::declval<T>()), bool())
{
return true;
}
template<typename>
constexpr bool allowed(...)
{
return false;
}
template<typename T>
std::string vec_to_str(const std::vector<T>& vec)
{
static_assert(allowed<T>(0), "Invalid value type.");
return "";
}
struct foo {};
int main()
{
std::vector<int> v_int;
vec_to_str(v_int);
std::vector<foo> v_double;
vec_to_str(v_double); // static_assert fires here
}
Since std::to_string
is a C++11 feature, I guess you might be open to a C++11 solution. In this particular case, you can use the trailing return type in a sfinae manner:
template <typename T>
auto vec_to_str(const std::vector<T>& vec) -> decltype(std::to_string(std::declval<T>()));
which would fail to substitute (and eliminate that overload) if the value-type does not work for to_string
. But still, that's not necessarily the most eye-pleasing way to document and enforce the rule. There is probably a pre-C++11 version of the above Sfinae trick too, but it won't be any prettier.
In general, I would say that it's fine to simply document it in the comments (possibly with a doxygen tag, like \tparam
). You could use a concept-check mechanism, in the style of Boost.Concept-Check if you want.
As a side note, for this specific case, I might recommend that you rely on the std::ostream
operator <<
instead of the to_string
function, since it is more likely that custom types (e.g., a 2D vector or something) will be equipped with an overload for outputting to a stream.
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