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;
}
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 istrue
, 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;
}
Before C++17 you can go with SFINAE or specialization (with templates), or just overloading (even without templates).