0

I am leaning the topic templates in C++, it says I can also assign the datatype in the template syntax. But if I pass a different datatype in the object of class and call the method of my class it should throw an error or a garbage output, but it does not whereas it gives the correct output if I assign the datatype while declaring the object of the class and calling it. Why is so?

Here is the program I was practicing on

#include <iostream>
using namespace std;
template <class t1 = int, class t2 = int>
class Abhi
{
public:
    t1 a;
    t2 b;
    Abhi(t1 x, t2 y)
    {
        a = x;
        b = y;**your text**
    }
    void display()
    {
        cout << "the value of a is " << a << endl;
        cout << "the value of b is " << b << endl;
    }
};
int main()
{
    Abhi A(5,'a');
    A.display();

    Abhi <float,int>N(5.3,8.88);
    N.display();

    return 0;
}

I am facing the issue in the first object A while the second object N gives the correct output

The output of the above program for the first object is the value of a is 5 the value of b is a

The output of the above program for the second object is the value of a is 5.3 the value of b is 8

Caleth
  • 52,200
  • 2
  • 44
  • 75
  • Type deduction from ctor call? – lorro Oct 26 '22 at 10:22
  • 2
    What exactly is the output you'd expect? – Ulrich Eckhardt Oct 26 '22 at 10:23
  • If I am passing a character while the datatype is int, the output should be the ASCII code – Abhishek Ojha Oct 26 '22 at 10:26
  • Okay. So the Q is why `t2` becomes `char` and doesn't remain `int`, perhaps. – Ulrich Eckhardt Oct 26 '22 at 10:28
  • yes or if not it should throw some garbage value or error like a basic program. – Abhishek Ojha Oct 26 '22 at 10:31
  • "the output should be the ASCII code" Can you point out the place in your code which should make it so? – n. m. could be an AI Oct 26 '22 at 10:34
  • **This has nothing to do with templates.** You want `std::cout << 'a';` to print the ascii code. See duplicate: [Output ASCII value of character](https://stackoverflow.com/questions/49494609/output-ascii-value-of-character) – Jason Oct 26 '22 at 10:35
  • 1
    @JasonLiam No. Op assumes the variable to have type `int` and therefore expects `std::cout << int{'a'};` to print the "ascii" code. Which it would if the variable had type `int` but it was deduced to `char` instead. – bitmask Oct 26 '22 at 10:37
  • @bitmask Yes, they just have to write `T1(a)` and `T2(b)`. – Jason Oct 26 '22 at 10:37
  • @JasonLiam it has a lot to do with templates, because they are expecting `Abhi` to mean `Abhi<>` – Caleth Oct 26 '22 at 10:38
  • @Caleth The fundamental problem isn't with the use of templates but with OP not knowing how to print the ascii. If one know that they can do `int(a)` then it is **trivial** to write `T1(a)` and `T2(b)`. – Jason Oct 26 '22 at 10:39
  • Thank you for your help everyone my doubts have been cleared. – Abhishek Ojha Oct 26 '22 at 10:42
  • @JasonLiam OP's expectation is that `Abhi A(5,'a');` declares an `Abhi`, because those are the default parameters of the template, and they are surprised that they get an `Abhi` via ctad, https://coliru.stacked-crooked.com/a/ade90c0cd867ea81 – Caleth Oct 26 '22 at 10:48
  • @Caleth A mistake is a mistake. It doesn't matter if it is done intentionally or not. OP seems to not be aware of CTAD as well as how to print the ascii. Also, instead of reopening the question, it would have been better to add dupes for CTAD. There are plenty of dupes for CTAD. Here is the dupe: [Why not infer template parameter from constructor?](https://stackoverflow.com/questions/984394/why-not-infer-template-parameter-from-constructor) – Jason Oct 26 '22 at 11:05
  • @JasonLiam I had a cursory look for "ctad ignores default template parameters" and didn't find anything. If you can find a question with that, and not just "what is CTAD", then mark it as a dupe. – Caleth Oct 26 '22 at 11:08
  • @Caleth I see. I found the following two: [Why can't constructors deduce template arguments?](https://stackoverflow.com/questions/29677505/why-cant-constructors-deduce-template-arguments) and [Why not infer template parameter from constructor?](https://stackoverflow.com/a/39087312/12002570) that are relevant for the question. – Jason Oct 26 '22 at 11:11
  • @JasonLiam relevant, but not dupes – Caleth Oct 26 '22 at 11:12
  • @Caleth The this maybe: [Deduce class template parameter with default](https://stackoverflow.com/questions/65784277/deduce-class-template-parameter-with-default) or even [template argument deduction for constructors](https://stackoverflow.com/questions/6971904/template-argument-deduction-for-constructors). – Jason Oct 26 '22 at 11:15
  • @Caleth Here is one more: [Class template argument deduction before C++17](https://stackoverflow.com/questions/53832483/class-template-argument-deduction-before-c17). All these posts are more useful than the current accepted answer. [Class template argument type deduction in C++17](https://stackoverflow.com/questions/62909403/class-template-argument-type-deduction-in-c17-compilation-problems). – Jason Oct 26 '22 at 11:18
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/249069/discussion-between-caleth-and-jason-liam). – Caleth Oct 26 '22 at 11:19

2 Answers2

1

A char can be implicitly converted to an int. Although the type of A will be deduced by C++20 to Abhi<int,char>. That's why when you output it you get an a and not its corresponding integer representation.

See CTAD for a more detailed explanation of the mechanism.

More interesting is why your compiler implicitly converts double to int or float in N. This indicates that your compiler warning flags are insufficiently high or you are actively ignoring them.

bitmask
  • 32,434
  • 14
  • 99
  • 159
  • can you please explain me the "compiler waring flag" part ? – Abhishek Ojha Oct 26 '22 at 10:37
  • @AbhishekOjha Your compiler can warn you about dangerous constructs or code that has a danger of doing something you didn't intend. For the compiler to do this, you have to pass it a number of options (or "flags"). And then you have to read the compiler output. The cast from double to int looses information and therefore your compiler should be configured in a way to warn you about that. How you accomplish this depends on your compiler. You can search here on SO or the larger net to find out. – bitmask Oct 26 '22 at 10:39
  • @bitmask g++ doesn't warn about narrowing conversions [here](https://coliru.stacked-crooked.com/a/869eb3cfcfffb233) – Caleth Oct 26 '22 at 10:47
  • @Caleth It does with `-Wconversion -Wsign-conversion -Wfloat-conversion`. – bitmask Oct 26 '22 at 10:51
  • yay, important warnings that are in neither `-Wall` nor `-Wextra`, thanks g++ – Caleth Oct 26 '22 at 10:54
  • @Caleth I understand and share your frustration there. These are not even in `-pedantic`. I usually have quite a catalogue of additional flags for gcc. Typically more than fits in one screen line, actually. But to be fair, clang doesn't do this either. – bitmask Oct 26 '22 at 10:59
-1

When you write Abhi A(5,'a');, it doesn't use the default arguments of the Abhi template, instead the template type arguments are deduced from the constructor arguments values, in this case A is an Abhi<int, char>. This is a process called Class Template Argument Deduction.

You would get the default arguments if you wrote Abhi<> A(5, 'a');.

When you write Abhi <float,int>N(5.3,8.88); you have specified the types, but C++ allows conversion between arithmetic types. Unfortunately that includes discarding the fractional part when converting a decimal to int. Often there are settings for your compiler to warn of or forbid these lossy conversions.

The conversion from char to int isn't problematic, because there is an int value for every char value.

We can see that all here

Caleth
  • 52,200
  • 2
  • 44
  • 75
  • There are already plenty of dupes for this. [Why not infer template parameter from constructor?](https://stackoverflow.com/questions/984394/why-not-infer-template-parameter-from-constructor). – Jason Oct 26 '22 at 11:46
  • @bitmask There are many factors(besides its usefullness) on which i judge an answer. For example, whether the answerer is already aware of dupes or not. If they're then there is no point in repeating the same thing over and over again. There are other factors too. Even though the tooltip of the upvote/downvote buttons only says that they're meant to indicate the usefullness of answer, I do not agree with that. Also, I used to get downvotes for answers that had dupes when I was new to the site and at that time I used to just add answer without looking for dupes. – Jason Oct 26 '22 at 11:55
  • @bitmask continued... I mean questions that are very frequent should be closed and answers should be downvoted. – Jason Oct 26 '22 at 11:57
  • @JasonLiam more evidence OP's mistake is reasonable: https://stackoverflow.com/questions/15373823/template-default-arguments shows us that `Abhi A;` would declare an `Abhi` – Caleth Oct 26 '22 at 11:57
  • @Caleth Yes then(for `Abhi A`) default arguments will be used as CTAD can't work there because we're not giving any argument to the ctor. But that is different from the current given program. – Jason Oct 26 '22 at 11:57
  • @JasonLiam yes! We have a *novel* question here – Caleth Oct 26 '22 at 11:58
  • @Caleth Haha!.... – Jason Oct 26 '22 at 11:58