How to make my function Len() return the size of Std::string, vector and const char *?

Asked

Viewed 942 times

0

My job len() in C++ can return the size of std::string and of std::vector<std::string> but cannot return the size of const char *, 'Cause for that or I’d have to use strlen() or convert const char * for std::string to use the method size. I couldn’t change the flow control with the if to check the type of data entered and redirect to the treatment as it would be easy in interpreted languages.

How to edit this function to return both the size of std::string and std::vector<std::string> as well as const char * in a very attractive way?

// Função len()
template < typename T >
int len( T args )
{
    return args.size();
}

std::string a = "Ola Mundo!";
const char * b = "Ola Mundo!";
std::vector<std::string> c = {"Ola", "Mundo", "!"};

std::cout << len(a) << "\n"; // Retorna 10.
std::cout << len(b) << "\n"; // error: request for member 'size' in 'args', which is of non-class type 'const char*'
std::cout << len(c) << "\n"; // Retorna 3.
  • Are you using C++17? If you are, why didn’t you ask the question?

2 answers

3

Is not if what you should do, is specialization (a much more advanced concept that doesn’t seem to be the case to learn now). So:

#include <iostream>
#include <string>
#include <vector>
#include <string.h>
using namespace std;

template<typename T>
int len(T args) { return args.size(); }
template<>
int len(const char *args) { return strlen(args); }

int main() {
    string a = "Ola Mundo!";
    const char *b = "Ola Mundo!";
    vector<string> c = {"Ola", "Mundo", "!"};
    cout << len(a) << "\n";
    cout << len(b) << "\n";
    cout << len(c) << "\n";
}

Behold working in the ideone. And in the repl it.. Also put on the Github for future reference.

The question originally did not say that I could use C++17, on the contrary it said about C++11 or C++14, with C++17 my answer would be:

#include <iostream>
#include <string>
#include <vector>
#include <string.h>
#include <type_traits>

using namespace std;

template<typename T>
int len(T args) {
    if constexpr (is_same_v<T, const char*>) return strlen(args);
    else return args.size(); 
}

int main() {
    string a = "Ola Mundo!";
    const char *b = "Ola Mundo!";
    vector<string> c = {"Ola", "Mundo", "!"};
    cout << len(a) << "\n";
    cout << len(b) << "\n";
    cout << len(c) << "\n";
}

Behold working in the GDB Online. Also put on the Github for future reference.

  • Thank you very much, it worked fine. So I won’t have to care if the text is string or const char * when picking up the size.

1


In addition to Maniero’s response, you can also use Std::is_same together with constexpr to validate specific type operations (C++17). This can help prevent code duplication if you happen to have multiple specializations.

#include <iostream>
#include <string>
#include <vector>
#include <string.h>
#include <type_traits>

using namespace std;

template<typename T>
int len(T args) {

    if constexpr (is_same_v<T, const char*>) {
        return strlen(args);
    } else {
        return args.size(); 
    }
}

int main() {
    string a = "Ola Mundo!";
    const char *b = "Ola Mundo!";
    vector<string> c = {"Ola", "Mundo", "!"};
    cout << len(a) << "\n";
    cout << len(b) << "\n";
    cout << len(c) << "\n";
}
  • Excellent! I appreciate Maniero’s reply, but that’s the perfect answer to what I’m looking for. It was just an if with this behavior that I needed. if constexpr will be essential in the flow control of my programs.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.