0

I tried to raise stack overflow using template like the following :

#include <iostream>

using namespace std;

#define endl '\n'

template <class T>
// void next (T a) cout << a++ << endl;       // can't write in a line without {}
void next (T a)
{
    if (typeid(a) == typeid((char) 'a') || typeid(a) == typeid((unsigned char) 'a'))
    {
        cout << typeid(a).name() << " : " << (int) a << " + 1 = " << (int) ++a << " (converted to ASCII value)" << endl;    
    } else
    {
        cout << typeid(a).name() << " : " << a << " + 1 = " << ++a << endl;
    }
    // there will be more alternatives like type_info and so on ……
}

int main()
{
    next((char) CHAR_MAX);
    next((unsigned char) UCHAR_MAX);
    next((short) SHRT_MAX);
    next((unsigned short) USHRT_MAX);
    next((int) INT_MAX);
    next((unsigned int) UINT_MAX);
    next((bool) 1);                     // warning: use of an operand of type 'bool' in 'operator++' is deprecated

    return 0;
}
  • results :
c : 127 + 1 = -128 (converted to ASCII value)
h : 255 + 1 = 0 (converted to ASCII value)
s : 32767 + 1 = -32768
t : 65535 + 1 = 0
i : 2147483647 + 1 = -2147483648
j : 4294967295 + 1 = 0
b : 1 + 1 = 1

This is an advanced code from my previous one using overloading similar functions for each data type(so shame, so it should be secret).

But now I have more question if I can compress the series of next() in main() more. I think it seems to require a container that can have various typed data; for example, {short 1, int 10, long long 100}.

Thank you for your advices & above all, take care of your health.

Kimpro
  • 81
  • 2
  • 11
  • 1
    You seem to be learning C++ the wrong way. Your terminology seems wrong and confusing. The question is very unclear. I have no clue what you are asking. – DeiDei Jul 25 '21 at 15:49
  • Well, I meant to find some efficient way more than using `next()` repeatably. So I thought, if there is a container that can have various typed elements, I could easily substitute it in `for` loop. – Kimpro Jul 25 '21 at 16:10
  • If I'm reading this correctly, it sounds like you want a `std::tuple`, and then use [this](https://stackoverflow.com/questions/16387354/template-tuple-calling-a-function-on-each-element) to call a function for each element of the tuple. – NathanOliver Jul 25 '21 at 16:11

1 Answers1

0

Indeed, I have no idea what are you asking so I try to answer some related questions and hope this will help :)

To find a maximum value of a type T, use numeric_limits<T>::max() function instead of macros. This way you can only specify the type to call your function:

next<char>();
next<unsigned char>();
next<short>();
...

In the function next I can see how you handle char types in a special way. There is a neat trick that saves you from using if. Expression +a (unary plus) triggers integer promotion and thus will yield you at least type int, which is properly printable as a number. So you can rewrite next like this:

template <class T>
void next()
{
  T a = std::numeric_limits<T>::max();
  T b = a + 1;
  std::cout << typeid(T).name() << " : " << +a << " + 1 = " << +b << std::endl;
}

Answering your original question, now when you got rid of macros in the calls of next you can "iterate" on the types to call it with. In c++ if you need a "collection of types" T1, T2, T3, you usually use std::tuple<T1, T2, T3>. However, in this particular case where you don't have to store this "collection" anywhere, it is actually easier to go with variadic templates and fold expressions:

template<class... Ts>
void print() {
    (next<Ts>(), ...);
}

int main()
{
  print<char, unsigned char, short, int>();
}

Note how expression (next<Ts>(), ...); expands into (next<char>(), next<unsigned char>(), next<short>(), next<int>());. This is a number of calls separated by operator comma.

As a final point, using ++a or a+1 to find a "next" number is incorrect, since overflowing signed integer types is undefined behavior. You won't necessarily get expected results.

Mikhail
  • 20,685
  • 7
  • 70
  • 146