Pointer templates? How many pointers? | SoloLearn: Learn to code for FREE!

0

Pointer templates? How many pointers?

Hi guys, have a look at these two functions. They're basically the same, except for the one asterisk that makes a pointer to a pointer. Does anyone know how to merge these two functions into 1? (PS the functions are supposed to print the contents of a container(vector, list, deque etc.). They both work if the datatype matches.) template <template<class...> class S, class T> void printcont(S<T> const &a) { typename S<T>::const_iterator itr; for (itr = a.cbegin(); itr != a.cend(); ++itr) std::cout << *itr << "\n"; } template <template<class...> class S, class T> void printptr(S<T> const &a) { typename S<T>::const_iterator itr; for (itr = a.cbegin(); itr != a.cend(); ++itr) std::cout << **itr << "\n"; }

5/24/2020 2:40:55 PM

Orville Vroemen

3 Answers

New Answer

+2

template <template<class...> class S, class T> void printcont(S<T> const &a) { typename S<T>::const_iterator itr; for (itr = a.cbegin(); itr != a.cend(); ++itr) { if constexpr ( std::is_pointer<T>::value ) { std::cout << **itr << '\n'; } else { std::cout << *itr << '\n'; } } } by using "if constexpr" statement the branch (std::is_pointer<T>::value) will get evaluated at compile time, and if it is true then every other branch (else if and else) gets discarded. If it is false, the next branch is checked (here else), and if it is true, discard every other branch, etc.

+1

Thanks Mohamed ELomari, just one more question, do you think it's better(for the sake of performance) to put the for loop inside of the if statement? Because, afaik, then the if statement wouldn't need to control the statement every iteration. Let me know! To eleborate, here's what I mean: template <template<class...> class S, class T> void printcont(S<T> const &a) { typename S<T>::const_iterator itr; if constexpr (std::is_pointer<T>::value) { for (itr = a.cbegin(); itr != a.cend(); ++itr) std::cout << **itr << '\n'; } else { for (itr = a.cbegin(); itr != a.cend(); ++itr) std::cout << *itr << '\n'; } }

+1

when the compiler will instantiate "printcont": ( let's say for S == std::vector) for T == int, it will look like this : void printcont(std::vector<int> const &a) { typename vector<int>::const_iterator itr; for (itr = a.cbegin(); itr != a.cend(); ++itr) { // if constexpr (std::is_pointer<int>::value ) { // discarded // std::cout << **itr << '\n'; // discarded // } // else { // this branch is taken std::cout << *itr << '\n'; // } } } for T == int*, it will look like this: void printcont(std::vector<int*> const &a) { typename vector<int*>::const_iterator itr; for (itr = a.cbegin(); itr != a.cend(); ++itr) { // if constexpr (std::is_pointer<int*>::value ) { // this branch is taken std::cout << **itr << '\n'; // } // else { // discarded // std::cout << *itr << '\n'; // #discarded // } } }