The following is an example of a class that iterates through an STL container and prints out each element, with the initialization code attached for the main().
It seems as if the compiler parses the entire ContainerPrinterClass at compile time and throws an error when it gets to a line that is unsupported by an element in one of the passed in STL containers, for example element.first/element.second
for type int
in the vector. Yet, it's not supposed to be even entering that condition because flow control clearly states to only enter it if (std::is_same<T, std::map<int, std::string>>::value)
is true.
The opposite is also true for when the map is passed into the print function and the compiler flags the error in the else
condition where it tries to print the element, which is a std::pair and can't. But it should not even be in that else condition, since if a map is passed it, execution goes to the if
condition and skips the else
entirely.
I've also attempted with trying to substitute the (typeid(*container) == typeid(std::map<int, std::string>))
and dynamic_cast
to check if the element is a std::pair
with same results, where the compiler parses all the conditions in the printer function (even the incorrect ones for a particular type) at compile time.
So does anyone know how to provide this kind of template/generic functionality akin to Java's instanceOf
and not have the compiler go blindly parsing the code in the conditions it's not supposed to go into for that particular type?
// the printer class
class ContainterPrinterClass {
public:
ContainterPrinterClass() {};
template<class T> void printElementsInContainer(T *container) {
// if container type is map, print key and value
if (std::is_same<T, std::map<int, std::string>>::value) {
for each (auto element in *container) {
std::cout << "key: " << element.first << " val: " << element.second << std::endl;
}
} else {
// else if container is a vector, print just element
for each (auto element in *container) {
std::cout << "val: " << element << std::endl;
}
}
}
};
// in main()
ContainterPrinterClass containerPrinterClass;
std::vector<int> vectorOfInts = {1};
containerPrinterClass.printElementsInContainer<std::vector<int>>(&vectorOfInts);
std::map<int, std::string> mapOfStrings = {std::pair<int, std::string>(2, "Two")};
containerPrinterClass.printElementsInContainer<std::map<int, std::string>>(&mapOfStrings);
This however it will not compile and is giving the following error:
1>e:\workbench\projects\visualstudio_workspaces\tuts\testbed1\basic_app\basic_app.cpp(503): error C2228: left of '.first' must have class/struct/union
1> type is 'int'
1> e:\workbench\projects\visualstudio_workspaces\tuts\testbed1\basic_app\basic_app.cpp(747) : see reference to function template instantiation 'void ContainterPrinterClass::printElementsInContainer<std::vector<int,std::allocator<_Ty>>>(T *)' being compiled
1> with
1> [
1> _Ty=int
1> , T=std::vector<int,std::allocator<int>>
1> ]
1>e:\workbench\projects\visualstudio_workspaces\tuts\testbed1\basic_app\basic_app.cpp(503): error C2228: left of '.second' must have class/struct/union
1> type is 'int'
1>e:\workbench\projects\visualstudio_workspaces\tuts\testbed1\basic_app\basic_app.cpp(508): error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'std::pair<const _Kty,_Ty>' (or there is no acceptable conversion)
1> with
1> [
1> _Kty=int
1> , _Ty=std::string
1> ]
1> c:\visualstudio2013pro\vc\include\ostream(498): could be 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(std::basic_streambuf<char,std::char_traits<char>> *)'
1> c:\visualstudio2013pro\vc\include\ostream(478): or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(const void *)'
1> c:\visualstudio2013pro\vc\include\ostream(458): or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(long double)'
1> c:\visualstudio2013pro\vc\include\ostream(438): or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(double)'
1> c:\visualstudio2013pro\vc\include\ostream(418): or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(float)'
1> c:\visualstudio2013pro\vc\include\ostream(397): or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(unsigned __int64)'
1> c:\visualstudio2013pro\vc\include\ostream(377): or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(__int64)'
1> c:\visualstudio2013pro\vc\include\ostream(356): or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(unsigned long)'
1> c:\visualstudio2013pro\vc\include\ostream(336): or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(long)'
1> c:\visualstudio2013pro\vc\include\ostream(316): or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(unsigned int)'
1> c:\visualstudio2013pro\vc\include\ostream(291): or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(int)'
1> c:\visualstudio2013pro\vc\include\ostream(271): or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(unsigned short)'
1> c:\visualstudio2013pro\vc\include\ostream(237): or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(short)'
1> c:\visualstudio2013pro\vc\include\ostream(217): or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(std::_Bool)'
1> c:\visualstudio2013pro\vc\include\ostream(210): or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(std::ios_base &(__cdecl *)(std::ios_base &))'
1> c:\visualstudio2013pro\vc\include\ostream(203): or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(std::basic_ios<char,std::char_traits<char>> &(__cdecl *)(std::basic_ios<char,std::char_traits<char>> &))'
1> c:\visualstudio2013pro\vc\include\ostream(197): or 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(std::basic_ostream<char,std::char_traits<char>> &(__cdecl *)(std::basic_ostream<char,std::char_traits<char>> &))'
1> c:\visualstudio2013pro\vc\include\ostream(699): or 'std::basic_ostream<char,std::char_traits<char>> &std::operator <<<char,std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,const char *)'
1> c:\visualstudio2013pro\vc\include\ostream(746): or 'std::basic_ostream<char,std::char_traits<char>> &std::operator <<<char,std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,char)'
1> c:\visualstudio2013pro\vc\include\ostream(784): or 'std::basic_ostream<char,std::char_traits<char>> &std::operator <<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,const char *)'
1> c:\visualstudio2013pro\vc\include\ostream(831): or 'std::basic_ostream<char,std::char_traits<char>> &std::operator <<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,char)'
1> c:\visualstudio2013pro\vc\include\ostream(957): or 'std::basic_ostream<char,std::char_traits<char>> &std::operator <<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,const signed char *)'
1> c:\visualstudio2013pro\vc\include\ostream(964): or 'std::basic_ostream<char,std::char_traits<char>> &std::operator <<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,signed char)'
1> c:\visualstudio2013pro\vc\include\ostream(971): or 'std::basic_ostream<char,std::char_traits<char>> &std::operator <<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,const unsigned char *)'
1> c:\visualstudio2013pro\vc\include\ostream(978): or 'std::basic_ostream<char,std::char_traits<char>> &std::operator <<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,unsigned char)'
1> c:\visualstudio2013pro\vc\include\ostream(988): or 'std::basic_ostream<char,std::char_traits<char>> &std::operator <<<char,std::char_traits<char>,std::pair<const _Kty,_Ty>>(std::basic_ostream<char,std::char_traits<char>> &&,const std::pair<const _Kty,_Ty> &)'
1> with
1> [
1> _Kty=int
1> , _Ty=std::string
1> ]
1> c:\visualstudio2013pro\vc\include\ostream(1026): or 'std::basic_ostream<char,std::char_traits<char>> &std::operator <<<char,std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,const std::error_code &)'
1> while trying to match the argument list '(std::basic_ostream<char,std::char_traits<char>>, std::pair<const _Kty,_Ty>)'
1> with
1> [
1> _Kty=int
1> , _Ty=std::string
1> ]
1> e:\workbench\projects\visualstudio_workspaces\tuts\testbed1\basic_app\basic_app.cpp(750) : see reference to function template instantiation 'void ContainterPrinterClass::printElementsInContainer<std::map<int,std::string,std::less<_Kty>,std::allocator<std::pair<const _Kty,_Ty>>>>(T *)' being compiled
1> with
1> [
1> _Kty=int
1> , _Ty=std::string
1> , T=std::map<int,std::string,std::less<int>,std::allocator<std::pair<const int,std::string>>>
1> ]