0% found this document useful (0 votes)
26 views

Assignment - 10 Solution

Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
26 views

Assignment - 10 Solution

Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 16

Programming in Modern C++: Assignment Week 10

Total Marks : 27

Partha Pratim Das


Department of Computer Science and Engineering
Indian Institute of Technology Kharagpur, Kharagpur – 721302
[email protected]

September 20, 2024

Question 1
Consider the program (in C++11) given below. [MCQ, Marks 1]

#include <iostream>

__________________ { // LINE-1
double dct = 0.05;
double getVal(double pri){
return pri * dct;
}
}

________________________ { // LINE-2
double dct = 0.07;
template<typename T>
T getVal(T pri){
return pri * dct;
}
}

int main(){
std::cout << ns1::getVal(105.0) << " ";
std::cout << ns2::getVal(105) << " " << getVal(105.0);
return 0;
}

Choose the appropriate option to fill in the blanks at LINE-1 and LINE-2 so that the output
becomes
5.25 7 7.35

a) LINE-1: namespace ns1


LINE-2: namespace ns2

b) LINE-1: namespace ns1


LINE-2: inline namespace ns2

c) LINE-1: inline namespace ns1


LINE-2: namespace ns2

1
d) LINE-1: inline namespace ns1
LINE-2: inline namespace ns2

Answer: b)
Explanation:
As per the output of ns1::getVal(105.0) and ns2::getVal(105), the ns1 and ns2 must
have basic namespace definition. However, since getVal(105.0) invoke the function getVal
from ns2, ns2 must be the default namespace. Thus, at LINE-1 and LINE-2, we must have:
namespace ns1
inline namespace ns2

2
Question 2
Consider the program (in C++11) given below. [MCQ, Marks 1]

#include <iostream>
int main( ){
int a = 1;
const int b = 1;
int& i1 = a;
const int& i2 = b;
auto x1 = i1;
auto x2 = i2; //LINE-1
std::cout << ++x1 << " " << ++x2 << " "; //LINE-2
std::cout << i1 << " " << i2;
return 0;
}

What will be the output/error?

a) Compiler error at LINE-1: auto connot deduce to cv-qualifier

b) Compiler error at LINE-2: read-only x2 cannot be modified

c) 2 2 2 2

d) 2 2 1 1

Answer: d)
Explanation:
Since auto never deduces adornments like cv-qualifer or reference (however, no error or excep-
tion is generated), the inferred type of x1 and x2 is int. Thus, the changes in x1 and x2 are
not reflected on i1 and i2.

3
Question 3
Consider the following code segment (in C++11). [MSQ, Marks 2]

#include <iostream>
#include <vector>
void change(std::vector<int>& iv){
auto j = 2;
for(________________ : iv) //LINE-1
i *= j;
}
int main( ){
std::vector<int> iVec { 10, 20, 30, 40 };
change(iVec);
for(auto i : iVec)
std::cout << i << ", ";
return 0;
}

Choose the appropriate option/s to fill in the blank at LINE-1 such that the output is
20, 40, 60, 80,

a) auto i

b) decltype(j) i

c) decltype((j)) i

d) decltype(iv[j]) i

Answer: c), d)
Explanation:
In options a) and b), the inferred type of i is int. Thus, the changes made in i are not
reflected in the vector iVec. So, the O/P is 20, 40, 60, 80,
In options c) and d), the inferred type of i is int&. Thus, the changes made in i are reflected
in the vector iVec.

4
Question 4
Consider the following code segment (in C++14). [MSQ, Marks 2]

#include<iostream>

struct LHS{
int i {10};
int operator()() { return i ; }
};

struct RHS{
int i {10};
int& operator()() { return i ; }
};

template < typename T >


_______________________________________ { //LINE-1
return rf() ;
}

int main(){
LHS f1;
RHS f2;
std::cout << caller(f1) << " ";
std::cout << (caller(f2) = 100);
return 0;
}

Choose the appropriate option/s to fill in the blank at LINE-1 such that the output is 10 100.

a) auto caller( T& rf )

b) auto caller( T& rf ) -> decltype(rf())

c) int& caller( T& rf )

d) decltype(auto) caller( T& rf )

Answer: b), d)
Explanation:
The call caller(f1) evaluates to prvalue of type int.
The call caller(f2) = 100 evaluates to lvalue of type int&.
Since plain auto never deduces to a reference, option a) fails for lvalue.
Since plain int& always deduces to a reference, option c) fails for prvalue.
Option b) and d) works for lvalue as well as prvalue. Thus these two are correct options.

5
Question 5
Consider the following code segment (in C++11). [MCQ, Marks 2]

#include <iostream>

int main( ){
int n = 10;

int& a = n;
const int& b = 10;

auto x1 = a;
auto x2 = b;
decltype(a) x3 = a;
decltype(b) x4 = a;

++x1; //LINE-1
++x2; //LINE-2
++x3; //LINE-3
++x4; //LINE-4

return 0;
}

Which of the following line/s generate/s compilation error/s?

a) LINE-1

b) LINE-2

c) LINE-3

d) LINE-4

Answer: d)
Explanation:
Since auto never deduces adornments like cv-qualifier or reference (however, no error or ex-
ception is generated), the inferred type of x1 and x2 is int. For x3, the inferred type is int&,
whereas for x4, the inferred type is const int&. Therefore, d) is the correct option.

6
Question 6
Consider the following code segment (in C++11). [MSQ, Marks 2]

#include<iostream>
#include<iomanip>

long double operator"" _M(long double x) {


return x * 100;
}
long double operator"" _CM(long double x) {
return x;
}
class distance{
public:
distance(int d1, int d2) : d1_(d1), d2_(d2){}
int getDistance(){ return d1_ + d2_; }
private:
int d1_, d2_;
};
int main() {
distance d(____________________); //LINE-1
std::cout << d.getDistance() << "CM";
return 0;
}

Choose the appropriate option to fill in the blank at LINE-1 such that the output is 1019CM.

a) 10.0M, 19.0CM

b) 10.0 M, 19.0 CM

c) (M)10.0, (CM)19.0

d) 10 M, 19 CM

Answer: b)
Explanation:
For user-defined numeric literal operators, the correct way to invoke them is to write them as
10.0 M, 19.0 CM.
All other options are compilation error. Even option d) is wrong as numeric literal operators
require exact type matching.
Intentionally kept as MSQ

7
Question 7
Consider the following program (in C++11). [MCQ, Marks 2]

#include <iostream>
#include <vector>
#include <initializer_list>

template<typename T>
class Number{
public:
Number() { std::cout << "1" << " "; }
Number(int n) { std::cout << "2" << " "; }
Number(std::initializer_list<int> elems) { std::cout << "3" << " "; }
Number(int n, std::initializer_list<int> elms) { std::cout << "4" << " ";
}
};
int main(){
Number<int> n1(10);
Number<int> n2({10, 20, 30});
Number<int> n3{10, 20, 30};
Number<int> n4 = {10, 20, 30};
Number<int> n5(10, {10, 20, 30});
return 0;
}

What will be the output?

a) 2 3 3 1 4

b) 2 3 3 3 4

c) 2 3 2 1 3

d) 2 4 3 3 4

Answer: b)
Explanation:
Number<int> n1(10); invokes parameterized constructor Number(int n) { ... }.
Number<int> n2({10, 20, 30});, Number<int> n3{10, 20, 30}; and Number<int> n4 =
{10, 20, 30}; invoke the initializer list constructor Number(initializer list<int> elms){
... }.
Number<int> n5(10, {10, 20, 30}); invokes the mixed constructor
Number(int n, initializer list<int> elms){ ... }.

8
Question 8
Consider the following code segment (in C++11). [MSQ, Marks 2]

#include<iostream>

constexpr int f2(const int i){


return i + 10;
}

void function(const int i){


constexpr int n = 20;
constexpr int c1 = n + 30; //LINE-1
constexpr int c2 = n + c1; //LINE-2
constexpr int c3 = n + i; //LINE-3
constexpr int c4 = n + f2(i); //LINE-4
}

int main(){
function(50);
return 0;
}

Identify the line/s that generate/s compilation error/s.

a) LINE-1

b) LINE-2

c) LINE-3

d) LINE-4

Answer: c), d)
Explanation:
constexpr needs compile-time constant.
At LINE-1, c1 = n + 30; where n is a constexpr and 30 is a literal. Therefore, c1 is a
constexpr.
At LINE-2, c2 = n + c1 where n and c1 both are constexpr. Therefore, c2 is a constexpr.
At LINE-3, c3 = n + i; where n is a constexpr; however i is not a compile-time constant.
Therefore, c2 cannot be constexpr.
At LINE-4, c4 = n + f2(i); where n is a constexpr; however the call f2(i) fails since i is not
a compile-time constant.

9
Question 9
Consider the following code segment (in C++11). [MSQ, Marks 2]

#include <iostream>

void show(char* str){ /*some code*/ }

template<typename FUNC, typename PARA>


void function(FUNC f, PARA p){
f(p);
}

int main(){
char s[15] = "Modern C++";
function(show, s); //LINE-1
function(show, 0); //LINE-2
function(show, s[4]); //LINE-3
function(show, nullptr); //LINE-4
return 0;
}

Choose the call/s to function that will result in compiler error/s.

a) LINE-1

b) LINE-2

c) LINE-3

d) LINE-4

Answer: b), c)
Explanation:
For the call in LINE-1, the template type parameter PARA is deduced to char*. Thus, it does
not generate any compiler error.
For the call in LINE-2, the template type parameter PARA is deduced to int. Thus, it generates
a compiler error.
For the call in LINE-3, the template type parameter PARA is deduced to char. Thus, it generates
a compiler error.
For the call in LINE-4, the template type parameter PARA is deduced to std::nullptr t and
the call show(f, std::nullptr t) is syntactically correct.

10
Programming Questions

Question 1
Consider the following program (in C++11). Fill in the blanks as per the instructions given
below:

• Fill in the blanks at LINE-1 and LINE-2 with appropriate headers for the definition of
function getValue() belongs to class G and class KG.

• Fill in the blank at LINE-3 with appropriate template definition.

• Fill in the blank at LINE-4 with appropriate header for function convert weight.

The program must satisfy the sample input and output. Marks: 3

#include <iostream>

class KG;
class G{
public:
G(double w) : w_(w) { }
KG getValue();
void print(){ std::cout << w_ << "G "; }
private:
double w_;
};

class KG{
public:
KG(double w) : w_(w) { }
G getValue();
void print(){ std::cout << w_ << "KG "; }
private:
double w_;
};

______________________ { return KG(w_ / 1000); } //LINE-1


______________________ { return G(w_ * 1000); } //LINE-2
______________________ //LINE-3
____________________________________ { //LINE-4
return w.getValue();
}

int main(){
double a, b;
std::cin >> a >> b;
G o1(a);
KG o2(b);
convert_weight(o1).print();
convert_weight(o2).print();
return 0;
}

11
Public 1
Input: 10 10
Output: 0.01KG 10000G

Public 2
Input: 2000 20
Output: 2KG 20000G

Private
Input: 50 500
Output: 0.05KG 500000G

Answer:
LINE-1: KG G::getValue()
LINE-2: G KG::getValue()
LINE-3: template <typename T>
Or
LINE-3: template <class T>
LINE-4: auto convert weight(T w) -> decltype(w.getValue())
Or
LINE-4: decltype(auto) convert weight(T w)
Explanation:
At LINE-1 and LINE-2 the header for getValue() function can be written as:
KG G::getValue()
and
G KG::getValue()
At LINE-3 the template, and at LINE-4 the header for function convert weight can be written
as:
template <typename T> or template <class T>
and
auto convert weight(T w) -> decltype(w.getValue()) in C++11/14
or
decltype(auto) convert weight(T w) in C++14

12
Question 2
Consider the following program in C++11/14. Fill in the blanks as per the instructions given
below:

• at LINE-1 with appropriate header and initialization list for the copy constructor,

• at LINE-2 with the appropriate header for copy assignment operator overload,

• at LINE-3 with appropriate header and initialization list for the move constructor,

• at LINE-4 with the appropriate header for move assignment operator overload,

such that it will satisfy the given test cases. Marks: 3

#include <iostream>
#include <vector>

class Integer {
public:
Integer(){}
Integer(int i) : ip_(new int(i)) { }
__________________________________ { } // LINE-1: copy constructor
_______________________________ { // LINE-2: copy assignment
if (this != &n) {
delete ip_;
ip_ = new int(*(n.ip_) * 10);
}
return *this;
}
~Integer() { delete ip_; }
__________________________ { n.ip_ = nullptr; } // LINE-3: move constructor
____________________________ { // LINE-4: move assignment
if (this != &d) {
ip_ = d.ip_;
d.ip_ = nullptr;
}
return *this;
}
void show(){
if(ip_ == nullptr)
std::cout << "moved : ";
else
std::cout << *ip_ << " : ";
}
private:
int* ip_ {nullptr};
};

int main(){
int a;
std::cin >> a;
Integer n1(a);
Integer n2 = n1;

13
Integer n3;
n3 = n1;
n1.show();
n2.show();
n3.show();

Integer n4 = std::move(n1);
Integer n5;
n5 = std::move(n1);
n1.show();
n4.show();
n5.show();
return 0;
}

Public 1
Input: 5
Output: 5 : 25 : 50 : moved : 5 : moved :

Public 2
Input: -10
Output: -10 : -50 : -100 : moved : -10 : moved :

Private
Input: 1
Output: 1 : 5 : 10 : moved : 1 : moved :

Answer:
LINE-1: Integer(const Integer& n) : ip (new int(*(n.ip ) * 5))
LINE-2: Integer& operator=(const Integer& n)
LINE-3: Integer(Integer&& n) : ip (n.ip )
LINE-4: Integer& operator=(Integer&& d)
Explanation:
As per the output specified, the header and initialization list for copy constructor at LINE-1
is:
Integer(const Integer& n) : ip (new int(*(n.ip ) * 10)),
the header for copy assignment operator for copy assignment is:
Integer& operator=(const Integer& n),
the header and initialization list for move constructor at LINE-3 is:
Integer(Integer&& n) : ip (n.ip ),
the header for move assignment at LINE-4 is:
Integer& operator=(Integer&& d).

14
Question 3
Consider the following program (in C++11). Fill in the blanks as per the instructions given
below:

• Fill in the blank at LINE-1 with an appropriate template definition.

• Fill in the blank at LINE-2 to complete the header for function inner product.

• Fill in the blank at LINE-3 to define the new type Tmp.

The program must satisfy the sample input and output. Marks: 3

#include <iostream>
#include <vector>

_________________________ //LINE-1
void inner_product(________________________) { //LINE-2
_______________________________; // LINE-3: define new type Tmp
/* Don't edit the following part */
Tmp sum = 0;

for (int i=0; i < v1.size(); ++i) {


sum += v1[i] * v2[i];
}
std::cout << sum << " ";
}

int main(){
float a;
int b;
double c;
std::vector<float> Vec1;
std::vector<int> Vec2;
for(int i = 0; i < 3; i++) {
std::cin >> a;
Vec1.push_back(a);
}
for(int i = 0; i < 3; i++) {
std::cin >> b;
Vec2.push_back(b);
}

inner_product(Vec1, Vec2);
return 0;
}

Public 1
Input:
1.5 2.5 3.5
1 2 3
Output: 17

15
Public 2
Input:
5.5 3.0 4.5
11 12 13
Output: 155

Private
Input:
3.14 3.15 3.15
10 20 30
Output: 188.9

Answer:
LINE-1: template<typename U, typename V>
Or
LINE-1: template<class U, class V>
LINE-2: std::vector<U>& v1, std::vector<V>& v2
LINE-3: typedef decltype(v1[0] * v2[0]) Tmp
Explanation:
At LINE-1, the appropriate template can be defined as:
template<typename U, typename V>
or template<class U, class V>
At LINE-2 the header for function inner product can be written as:
void inner product(std::vector<U>& v1, std::vector<V>& v2)
At LINE-3 the new type Tmp can be created as:
typedef decltype(v1[0] * v2[0]) Tmp

16

You might also like