the concept of templates is quite difficult to grasp quickly. I need a class member function to iterate over vector of any objects and print them all out. Can I do this with using templates? I.e.:
void SomeClass::printAll(std::vector< any type here> array) {
for (auto & o : array) {
std::cout << o << std::end;
}
}
If this is possible in C++, how would I define it in the header and implementation files, I dare guess the syntax might be different.
Many thanks in advance for helping with this naive questions.
Trying to grasp any non-trivial topic quickly is difficult. Just don't do it, but go slowly. That also means not trying to understand more than one thing at a time. I don't know why that function has to be member of a class. Make it a free function:
template <typename T>
void printAll(const std::vector<T>& vect) {
for (const auto& o : vect) {
std::cout << o << "\n";
}
}
Don't pass by value when you can pass by const reference. I would prefer \n here rather than std::endl (not std::end) because std::endl flushes the stream. Choose names carefully, a std::vector is not an array.
The above will only work with vectors, but it can be more flexible for example by passing iterators:
template <typename IT>
void printAll(IT begin, IT end) {
for ( ; begin != end; ++begin) {
std::cout << *begin << "\n";
}
}
Related
Trying to say goodbye to SFINAE.
Is it possible to use concepts to distinguish between functions, so the compiler can match the correct function based on whether or not a sent parameter meets concept constraints?
For example, overloading these two:
// (a)
void doSomething(auto t) { /* */ }
// (b)
void doSomething(ConceptA auto t) { /* */ }
So when called the compiler would match the correct function per each call:
doSomething(param_doesnt_adhere_to_ConceptA); // calls (a)
doSomething(param_adheres_to_ConceptA); // calls (b)
Related question: Will Concepts replace SFINAE?
Yes concepts are designed for this purpose. If a sent parameter doesn't meet the required concept argument the function would not be considered in the overload resolution list, thus avoiding ambiguity.
Moreover, if a sent parameter meets several functions, the more specific one would be selected.
Simple example:
void print(auto t) {
std::cout << t << std::endl;
}
void print(std::integral auto i) {
std::cout << "integral: " << i << std::endl;
}
Above print functions are a valid overloading that can live together.
If we send a non integral type it will pick the first
If we send an integral type it will prefer the second
e.g., calling the functions:
print("hello"); // calls print(auto)
print(7); // calls print(std::integral auto)
No ambiguity -- the two functions can perfectly live together, side-by-side.
No need for any SFINAE code, such as enable_if -- it is applied already (hidden very nicely).
Picking between two concepts
The example above presents how the compiler prefers constrained type (std::integral auto) over an unconstrained type (just auto). But the rules also apply to two competing concepts. The compiler should pick the more specific one, if one is more specific. Of course if both concepts are met and none of them is more specific this will result with ambiguity.
Well, what makes a concept be more specific? if it is based on the other one1.
The generic concept - GenericTwople:
template<class P>
concept GenericTwople = requires(P p) {
requires std::tuple_size<P>::value == 2;
std::get<0>(p);
std::get<1>(p);
};
The more specific concept - Twople:
class Any;
template<class Me, class TestAgainst>
concept type_matches =
std::same_as<TestAgainst, Any> ||
std::same_as<Me, TestAgainst> ||
std::derived_from<Me, TestAgainst>;
template<class P, class First, class Second>
concept Twople =
GenericTwople<P> && // <= note this line
type_matches<std::tuple_element_t<0, P>, First> &&
type_matches<std::tuple_element_t<1, P>, Second>;
Note that Twople is required to meet GenericTwople requirements, thus it is more specific.
If you replace in our Twople the line:
GenericTwople<P> && // <= note this line
with the actual requirements that this line brings, Twople would still have the same requirements but it will no longer be more specific than GenericTwople. This, along with code reuse of course, is why we prefer to define Twople based on GenericTwople.
Now we can play with all sort of overloads:
void print(auto t) {
cout << t << endl;
}
void print(const GenericTwople auto& p) {
cout << "GenericTwople: " << std::get<0>(p) << ", " << std::get<1>(p) << endl;
}
void print(const Twople<int, int> auto& p) {
cout << "{int, int}: " << std::get<0>(p) << ", " << std::get<1>(p) << endl;
}
And call it with:
print(std::tuple{1, 2}); // goes to print(Twople<int, int>)
print(std::tuple{1, "two"}); // goes to print(GenericTwople)
print(std::pair{"three", 4}); // goes to print(GenericTwople)
print(std::array{5, 6}); // goes to print(Twople<int, int>)
print("hello"); // goes to print(auto)
We can go further, as the Twople concept presented above works also with polymorphism:
struct A{
virtual ~A() = default;
virtual std::ostream& print(std::ostream& out = std::cout) const {
return out << "A";
}
friend std::ostream& operator<<(std::ostream& out, const A& a) {
return a.print(out);
}
};
struct B: A{
std::ostream& print(std::ostream& out = std::cout) const override {
return out << "B";
}
};
add the following overload:
void print(const Twople<A, A> auto& p) {
cout << "{A, A}: " << std::get<0>(p) << ", " << std::get<1>(p) << endl;
}
and call it (while all the other overloads are still present) with:
print(std::pair{B{}, A{}}); // calls the specific print(Twople<A, A>)
Code: https://godbolt.org/z/3-O1Gz
Unfortunately C++20 doesn't allow concept specialization, otherwise we would go even further, with:
template<class P>
concept Twople<P, Any, Any> = GenericTwople<P>;
Which could add a nice possible answer to this SO question, however concept specialization is not allowed.
1 The actual rules for Partial Ordering of Constraints are more complicated, see: cppreference / C++20 spec.
this template prints the content of an 2D vector
how would you generalize this template so it works for every STL container ?
template<class T>
void printVector(std::vector<std::vector<T>> const &matrix) {
for (std::vector<T> row : matrix) {
for (T val : row) {
std::cout << val << " ";
}
std::cout << '\n';
}
}
Is there maybe "print" that allows me to print anything, no matter what I put into it ? (n-dimensional containers, strings, etc ?)
Just take any type and use range based loops. Your only problem is that you specified that is was a std::vector.
template<class T>
void print2Dcontainer(const T &matrix)
{
for (const auto &row : matrix)
{
for (const auto &val : row) std::cout << val << ' ';
std::cout << '\n';
}
}
My version above has no safety for passing something that will cause a compile error (e.g. passing 7). Fancy SFINAE could be added to remove this potential issue, but I'd only do so for library code.
I have a "dictionary" std::map<std::string, boost::any> (or std::any, if you want) that can possibly be nested. Now, I would like to display the map. Since boost::any obviously doesn't play nicely with <<, things are getting a little nasty. So far, I'm checking the type, cast it, and pipe the cast to cout:
for (const auto &p: map) {
std::cout << std::string(indent + 2, ' ') << p.first << ": ";
if (p.second.type() == typeid(int)) {
std::cout << boost::any_cast<int>(p.second);
} else if (p.second.type() == typeid(double)) {
std::cout << boost::any_cast<double>(p.second);
} else if (p.second.type() == typeid(std::string)) {
std::cout << boost::any_cast<std::string>(p.second);
} else if (p.second.type() == typeid(const char*)) {
std::cout << boost::any_cast<const char*>(p.second);
} else if (p.second.type() == typeid(std::map<std::string, boost::any>)) {
show_map(
boost::any_cast<std::map<std::string, boost::any>>(p.second),
indent + 2
);
} else {
std::cout << "[unhandled type]";
}
std::cout << std::endl;
}
std::cout << std::string(indent, ' ') << "}";
This prints, for example
{
fruit: banana
taste: {
sweet: 1.0
bitter: 0.1
}
}
Unfortunately, this is hardly scalable. I'd have to add another else if clause for every type (e.g., float, size_t,...), which is why I'm not particularly happy with the solution.
Is there a way to generalize the above to more types?
One thing you can do to lessen (but not remove) the pain is to factor the type determination logic into one support function, while using static polymorphism (specifically templates) for the action to be applied to the values...
#include <iostream>
#include <boost/any.hpp>
#include <string>
struct Printer
{
std::ostream& os_;
template <typename T>
void operator()(const T& t)
{
os_ << t;
}
};
template <typename F>
void f_any(F& f, const boost::any& a)
{
if (auto p = boost::any_cast<std::string>(&a)) f(*p);
if (auto p = boost::any_cast<double>(&a)) f(*p);
if (auto p = boost::any_cast<int>(&a)) f(*p);
// whatever handling for unknown types...
}
int main()
{
boost::any anys[] = { std::string("hi"), 3.14159, 27 };
Printer printer{std::cout};
for (const auto& a : anys)
{
f_any(printer, a);
std::cout << '\n';
}
}
(With only a smidge more effort, you could have the type-specific test and dispatch done for each type in a variadic template parameter pack, simplifying that code and the hassle of maintaining the list. Or, you could just use a preprocessor macro to churn out the if-cast/dispatch statements....)
Still - if you know the set of types, a boost::variant is more appropriate and already supports similar operations (see here).
Yet another option is to "memorise" how to do specific operations - such as printing - when you create your types:
#include <iostream>
#include <boost/any.hpp>
#include <string>
#include <functional>
struct Super_Any : boost::any
{
template <typename T>
Super_Any(const T& t)
: boost::any(t),
printer_([](std::ostream& os, const boost::any& a) { os << boost::any_cast<const T&>(a); })
{ }
std::function<void(std::ostream&, const boost::any&)> printer_;
};
int main()
{
Super_Any anys[] = { std::string("hi"), 3.14159, 27 };
for (const auto& a : anys)
{
a.printer_(std::cout, a);
std::cout << '\n';
}
}
If you have many operations and want to reduce memory usage, you can have the templated constructor create and store a (abstract-base-class) pointer to a static-type-specific class deriving from an abstract interface with the operations you want to support: that way you're only adding one pointer per Super_Any object.
Since you're already using Boost you could consider boost::spirit::hold_any.
It already has pre-defined streaming operators (both operator<<() and operator>>()).
Just the embedded type must have the corresponding operator defined, but in your use context this seems to be completely safe.
Despite being in the detail namespace, hold_any is quite widespread and almost a ready-to-use boost:any substitute (e.g. Type Erasure - Part IV, Why you shouldn’t use boost::any)
A recent version of Boost is required (old versions had a broken copy assignment operator).
Basically, I am implementing a container class. I need to create a method which sorts the data according to the comparator function/functor which must be passed with the sort request. Since declaration and definition of the method are in different files(.h and .cpp) using templates becomes a problem (and I don't have much experience using them). In other words, I want to make a method:
void sort(function/functor f);
and I don't know how to define the function. So, is there any solution to this problem?
If you know the signature of the function/functor to be passed[*], you can use std::function. Or boost::function if you don't have C++11. So for a comparator it would be:
void sort(std::function<bool(const Element&, const Element&)> f);
where Element is the type of the elements of the container.
Failing that you could define a class with a virtual compare function, and allow callers to derive from it with their own class. It's more work for callers, but that's exactly what std::function provides: a way for callers to not have to do that.
Two warnings:
make sure there's really a good reason for the implementation of your container not to be in the header file. All of the standard containers are implemented in header files, and that mostly works OK.
make sure there's really a good reason for you to implement a sort function. Standard containers only have sort functions where std::sort doesn't work: std::list and std::forward_list.
[*] Actually std::function doesn't require the exact same signature. You just say the types you want to call it with and the type you want to convert the return value to. So if you call it with two ints and the caller provides a function that takes two longs, then that's fine. The arguments are converted just like the function call would without any std::function.
This is generally done with templates. Like this:
#include <iostream> // For example output only.
template <typename F>
void sort(F&& pred) {
pred(123);
}
void normal_func(int v) {
std::cout << "normal_func(" << v << ")\n";
}
struct my_pred {
void operator()(int v) const {
std::cout << "my_pred(" << v << ")\n";
}
};
int main() {
sort([](int v) { std::cout << "Called lambda func with " << v << '\n'; });
sort(normal_func);
sort(my_pred());
}
If, however, templates cannot be used, then your best bet would be to use polymorphic function wrapper like std::function (or boost::function, or you can write your own simple version).
Alternatively, you can use a hardcore C-style regular function along with a void pointer where user can save their context. For example, like qsort(). Though I'd try not to go there if possible.
Here is an example using std::function:
#include <iostream> // For example output only.
#include <functional> // For std::function.
void sort(const std::function<void(int)>& pred) {
pred(123);
}
void normal_func(int v) {
std::cout << "normal_func(" << v << ")\n";
}
struct my_pred {
void operator()(int v) const {
std::cout << "my_pred(" << v << ")\n";
}
};
int main() {
sort([](int v) { std::cout << "Called lambda func with " << v << '\n'; });
sort(normal_func);
sort(my_pred());
}
Hope it helps.
You can use std::function as suggested in Steve Jessop's answer but in this case I think you should consider making your sort function a template function as in Vlad's answer. A sort function has to call the comparator many times and there will be noticeable overhead to using std::function in this situation.
The easiest solution is to use a template:
class C
{
template<typename T>
void sort(T func)
{
func(12,45); // Will compile as long as your function/functor
} // Can take two integers as parameters.
}; // NOTE: or integers can be converted into your parameters.
If you want to specify using old C notation.
typedef void (*FUNC_TYPE)(int, int); // declares a function pointer type.
// returns void takes two integers.
class C
{
void sort(FUNC_TYPE func)
{
func(12,45); // Compiles only if the function
} // matches the exact type.
};
The C++11 way
class C
{
void sort(std::function<void(int,int)> func)
{
func(12,45); // Will match any func/functor that
// will return a void and takes two
} // integers.
};
I wish I could just print contents of a set/vector/map by using cout << . It doesn't seem so difficult for the stl designers to implement : Assuming that << is defined for T, << for a container could just iterate through the elements and print them using ofstream << .
Is there an easy way to print them that I dont know of?
If not, Is there an easy solution? I have read at places that extending stl classes is a bad idea. Is that so, and why?
how about defining an something like an overloaded print function?
EDIT:
I am looking for a recursive function which can handle containers of containers of ...
I agree that different people would like different formats, but something overridable is better than nothing
Probably the easiest way to output an STL container is
std::copy(cont.begin(), cont.end(),
std::ostream_iterator<Type>(std::cout, " "));
where Type is the type of the elements of cont (e.g. if cont is of type std::vector<int> then Type must be int).
Of course instead of std::cout you can use any ostream.
In C++11 you can use range-based for:
for (auto& i: container) cout << i << " ";
cout << endl;
The easiest eay to dump a container is probably just using std::copy(). For example I typically use something like this:
template <typename C>
std::string format(C const& c) {
std::ostringstream out;
out << "[";
if (!c.empty()) {
std::copy(c.begin(), --c.end(),
std::ostream_iterator<typename C::value_type>(out, ", "));
out << c.back();
}
out << "]";
return out.str();
}
Yes, this doesn't always work but works for my needs. This actually shows one of the problems why there is no output for containers in the standard library: there are many different ways how containers can be formatted. To make matters worse, the formatted output should be readable where thing become real fun. All of this is doable but I'm not aware of a corresponding proposal.
It doesn't seem so difficult for the stl designers to implement : Assuming that << is defined for T, << for a container could just iterate through the elements and print them using ofstream << .
Of course it is not hard for them. However, ask yourself: Does the format of the output make sense for every client? The standard library is about reuse and genericity. Coupling containers with some arbitrary output formatting rules makes them less generic for the sake of only some.
The recommended solution therefore is to provide your own operator<<(std::ostream &, T) and/or to take other generic algorithms, as found in e.g. <algorithms>.
Are you looking something like this?
#include <iostream>
#include <set>
template <typename T>
std::ostream& operator<< (std::ostream& os, const std::set<T>& s)
{
for( auto i: s ) {
os << i << " ";
}
return os;
}
Then you just may use it this way:
std::set<int> my_set = { 11, 12, 13 };
std::cout << my_set << std::endl;
Using Template template parameter makes it easy, in order to make it working for each collection you need both template<class, class...> class X and class... Args as template parameters:
template<class T, template<class, class...> class X, class... Args>
std::ostream& operator <<(std::ostream& os, const X<T, Args...>& objs) {
os << "{";
bool commoFlag = false;
for (auto const& obj : objs) {
os << (commoFlag ? ", " : "") << obj;
commoFlag = true;
}
os << "}";
return os;
}
vector<float> f_vec{ 1.3f , 5.134f, 5.78f };
list<char> c_lst{ 'F','O', 'M', 'S', 'A' };
set<int> i_st{ 17,14, -70 };
std::cout << f_vec << std::endl;
std::cout << c_lst << std::endl;
std::cout << i_st << std::endl;
output:
{1.3, 5.134, 5.78}
{F, O, M, S, A}
{-70, 14, 17}