Search code examples
c++windowstemplatestypeid

Typeid() Check of Passing Paramaters of A Templated Function


I don't want to use function overload for a small change in a function. Instead, I want to use typeid() check of passing parameter of the templated function below. But, If I don't comment out the line in the code below, it gives the compile error of:

Severity    Code    Description Project File    Line    Suppression State
Error       invalid operands to binary expression ('basic_ostream<char, std::char_traits<char> >' and 'std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >')

As I understand the compiler does not know how to behave. Is there a solution for this?

The code is :

#include <iostream>
#include <vector>

using namespace std;


template <class T>
void Test(T A)
{
    if (typeid(T) == typeid(vector<string>)) {
        cout << "The type of A is vector<string>" << endl << endl;
        //cout << "First element of A is:" << A[0] << endl;    // If I don't comment out this line, it gives the compiler error.
    }

    if (typeid(T) == typeid(vector<vector<string>>)) {
        cout << "The type of A is vector<vector<string>>" << endl;
        cout << "First row first element of A is:" << A[0][0] << endl;
    }
}

int main()
{
    Test(vector<string> {"1", "2", "3"});

    Test(vector<vector<string>> { {"11", "12", "13"}, { "21", "22", "23" }});

    return 0;
}

Solution

  • The problem is in ordinary if, the statement-true (and statement-false if present) has to be valid statement at compile-time, no matter what's the result of the condition, for every instantiation of Test with the type T given.

    You can use constexpr if since C++17 (with std::is_same).

    In a constexpr if statement, the value of condition must be a contextually converted constant expression of type bool. If the value is true, then statement-false is discarded (if present), otherwise, statement-true is discarded.

    e.g.

    if constexpr (std::is_same_v<T, vector<string>>) {
        cout << "The type of A is vector<string>" << endl << endl;
        cout << "First element of A is:" << A[0] << endl;
    } 
    
    if constexpr (std::is_same_v<T, vector<vector<string>>>) {
        cout << "The type of A is vector<vector<string>>" << endl;
        cout << "First row first element of A is:" << A[0][0] << endl;
    }
    

    LIVE

    Before C++17 you can go with SFINAE or specialization (with templates), or just overloading (even without templates).