Assignment 10 Solution
Assignment 10 Solution
Total Marks : 27
Question 1
Consider the program (in C++11) given below. [MCQ, Marks 2]
#include <iostream>
__________________________ { // LINE-1
double dct = 0.05;
double getDct(double pri){
return pri * dct;
}
}
__________________________ { // LINE-2
double dct = 0.07;
template<typename T>
T getDct(T pri){
return pri * dct;
}
}
int main(){
std::cout << ver1_0::getDct(105.0) << " ";
std::cout << ver2_0::getDct(105) << " " << getDct(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
1
d) LINE-1: inline namespace ver1 0
LINE-2: inline namespace ver2 0
Answer: b)
Explanation:
As per the output of ver1 0::getDct(105.0) and ver2 0::getDct(105), the ver1 0 and
ver2 0 must have basic namespace definition. However, since getDct(105.0) invoke the func-
tion getDct from ver2 0, ver2 0 must be the default namespace. Thus, at LINE-1 and LINE-2,
we must have:
namespace ver1 0
inline namespace ver2 0
2
Question 2
Consider the program (in C++11) given below. [MCQ, Marks 2]
#include <iostream>
int main( ){
int n1 = 10;
const int n2 = 10;
int& i1 = n1;
const int& i2 = n2;
auto x1 = i1;
auto x2 = i2; //LINE-1
std::cout << ++x1 << " " << ++x2 << " "; //LINE-2
std::cout << i1 << " " << i2;
return 0;
}
c) 11 11 11 11
d) 11 11 10 10
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>
Choose the appropriate option/s to fill in the blank at LINE-1 such that the output is
20, 30, 40, 50,
a) auto i
b) decltype(j) i
c) decltype((j)) i
d) decltype(iv[j]) i
Answer: c), d)
Explanation:
In option 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, 30, 40, 50,
In option 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 LFunc{
int i {10};
int operator()() { return i ; }
};
struct RFunc{
int i {10};
int& operator()() { return i ; }
};
int main(){
LFunc f1;
RFunc f2;
std::cout << caller(f1) << " ";
std::cout << (caller(f2) = 20);
return 0;
}
Choose the appropriate option/s to fill in the blank at LINE-1 such that the output is 10 20.
Answer: b), d)
Explanation:
The call caller(f1) evaluates to prvalue of type int.
The call caller(f2) = 20 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). [MSQ, Marks 2]
#include <iostream>
class point{
public:
constexpr point(int x = 0, int y = 0) : x_(x), y_(y){ }
private:
int x_, y_;
};
int genN(){
return 10;
}
constexpr int genN(int i, int j){
return i + j;
}
int main(){
constexpr point p1 {100, 200}; //LINE-1
constexpr int i = 10;
int j = 20;
constexpr point p2 {i, j}; //LINE-2
constexpr point p3(genN(), genN()); //LINE-3
constexpr point p4(genN(i, j), genN(i, j)); //LINE-4
return 0;
}
Identify the function call/s that will compile without generating any error.
a) LINE-1
b) LINE-2
c) LINE-3
d) LINE-4
Answer: a)
Explanation:
Since the constructor of class point is constexpr type, it accepts all the parameters that
are constants.
At LINE-1, the actual parameters are compile-time constants. Therefore, options a) is correct.
At LINE-2 the actual parameters are variables. Likewise, at LINE-3 the actual parameters are
the return values of genN function that returns non-constant values. Therefore, options b) and
c) generate compiler errors.
Since genN(int i, int j) is constexpr type, it accepts all the parameters that are constants.
Therefore, LINE-4 also generates compiler error.
Intentionally kept as MSQ.
6
Question 6
Consider the following code segment (in C++11). [MSQ, Marks 2]
#include<iostream>
#include<iomanip>
Choose the appropriate option to fill in the blank at LINE-1 such that the output is 5011M.
a) 5.0KM, 11.0M
c) (KM)5.0, (M)11.0
d) 5 KM, 11 M
Answer: b)
Explanation:
For user-defined numeric literal operators, the correct way to invoke them is to write them as
5.0 KM, 11.0 M.
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>
class base{
public:
base(const int& x) { std::cout << "#1 " ; }
base(const base& ob) { std::cout << "#2 " ; }
base(base&& ob) noexcept { std::cout << "#3 " ; }
};
int main(){
derived o1(100, 200);
derived o2(o1);
derived o3(std::move(o1));
return 0;
}
a) #1 #4 #2 #5 #3 #6
b) #1 #4 #2 #5 #2 #6
c) #1 #4 #2 #5 #3 #5
d) #1 #4 #2 #6 #2 #6
Answer: b)
Explanation:
The statement o1(100, 200) invokes the parameterized constructor of derived class, which
forwards the call to the parameterized constructor of base class. It prints #1 #4.
The statement derived o2(o1) invokes the copy constructor of derived class, which forwards
the call to the copy constructor of base class. It prints #2 #5.
The statement o3(std::move(o1)) invokes the move constructor of derived class, which
(however) forwards the call to the copy constructor of base class. It prints #2 #6.
8
Question 8
Consider the following code segment (in C++11). [MCQ, Marks 2]
#include <iostream>
#include <list>
#include <initializer_list>
class items{
public:
items(int n) { std::cout << "#1 " ; }
items(std::initializer_list<int> vals) { std::cout << "#2 " ; }
items(int n, std::initializer_list<int> vals) { std::cout << "#3 " ; }
};
int main(){
items i1(10); //LINE-1
items i2{10, 20, 30}; //LINE-2
items i3({10}); //LINE-3
items i4{10}; //LINE-4
items i5 = {10}; //LINE-5
items i6(10, {10, 20, 30}); //LINE-6
return 0;
}
a) #1 #2 #1 #1 #1 #3
b) #1 #2 #1 #1 #1 #2
c) #1 #2 #1 #2 #2 #3
d) #1 #2 #2 #2 #2 #3
Answer: d)
Explanation:
The statement at LINE-1 invokes the constructor items(int n). However, all the statements
at LINE-2, LINE-3, LINE-4 and LINE-5 invoke the constructor items(std::initializer list<int>
vals). The statement at LINE-6 invokes the constructor items(int n, std::initializer list<int>
vals).
9
Question 9
Consider the following code segment (in C++11). [MSQ, Marks 2]
#include <iostream>
int main(){
char s[4] = "C++";
wrapper(print, s); //LINE-1
wrapper(print, 0); //LINE-2
wrapper(print, s[4]); //LINE-3
wrapper(print, nullptr); //LINE-4
return 0;
}
Choose the call/s to wrapper 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 print(f, std::nullptr t) is syntactically correct.
10
Programming Questions
Question 1
Consider the following program (in C++11).
• Fill in the blank at LINE-1 with appropriate header for overloading copy assignment
operator.
• Fill in the blank at LINE-2 with appropriate header and initialization list for move
constructor.
• Fill in the blank at LINE-3 with appropriate header for overloading move assignment
operator.
The program must satisfy the sample input and output. Marks: 3
#include <iostream>
#include <vector>
class item {
public:
item() : cp_(nullptr) { }
item(char c) : cp_(new char(c)) { }
_______________________________ { // LINE-1: copy assignment
if (this != &ob) {
delete cp_;
cp_ = new char(*(ob.cp_) + 1);
}
return *this;
}
_______________________________ { // LINE-2: move constructor
ob.cp_ = nullptr; }
_______________________________ { // LINE-3: move assignment
if (this != &ob) {
cp_ = ob.cp_;
ob.cp_ = nullptr;
}
return *this;
}
void print(){
if(cp_ == nullptr)
std::cout << "moved, ";
else
std::cout << *cp_ << ", ";
}
~item() { delete cp_; }
private:
char* cp_ = nullptr;
};
11
int main(){
char a;
std::cin >> a;
item i1(a);
item i2;
i2 = i1;
i1.print();
i2.print();
item i3 = std::move(i1);
item i4;
i4 = std::move(i1);
i1.print();
i3.print();
i4.print();
return 0;
}
Public 1
Input: X
Output: X, Y, moved, X, moved,
Public 2
Input: a
Output: a, b, moved, a, moved,
Private
Input: H
Output: H, I, moved, H, moved,
Answer:
LINE-1: item& operator=(const item& ob)
LINE-2: item(item&& ob) : cp (ob.cp )
LINE-3: item& operator=(item&& ob)
Explanation:
At LINE-1, the header for overloading copy assignment operator can be written as:
item& operator=(const item& ob)
At LINE-2, the header and initialization list for move constructor can be written as:
item(item&& ob) : cp (ob.cp )
At LINE-3, the header for overloading move assignment operator can be written as:
item& operator=(item&& ob)
12
Question 2
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 Gram and class KiloGram.
• 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 KiloGram;
class Gram{
public:
Gram(double w) : w_(w) { }
KiloGram getValue();
void print(){ std::cout << w_ << "G "; }
private:
double w_;
};
class KiloGram{
public:
KiloGram(double w) : w_(w) { }
Gram getValue();
void print(){ std::cout << w_ << "KG "; }
private:
double w_;
};
int main(){
double a, b;
std::cin >> a >> b;
Gram o1(a);
KiloGram o2(b);
convert_weight(o1).print();
convert_weight(o2).print();
return 0;
}
Public 1
Input: 100 100
13
Output: 0.1KG 100000G
Public 2
Input: 2000 20
Output: 2KG 20000G
Private
Input: 500 500
Output: 0.5KG 500000G
Answer:
LINE-1: KiloGram Gram::getValue()
LINE-2: Gram KiloGram::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:
KiloGram Gram::getValue()
and
Gram KiloGram::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
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;
int main(){
float a;
int b;
double c;
std::vector<float> fVec;
std::vector<int> iVec;
std::vector<double> dVec;
for(int i = 0; i < 3; i++) {
std::cin >> a;
fVec.push_back(a);
}
for(int i = 0; i < 3; i++) {
std::cin >> b;
iVec.push_back(b);
}
for(int i = 0; i < 3; i++) {
std::cin >> c;
dVec.push_back(c);
}
inner_product(fVec, iVec);
inner_product(dVec, fVec);
return 0;
}
Public 1
Input:
15
1.5 2.5 3.5
1 2 3
1.2 2.2 3.2
Output: 17 18.5
Public 2
Input:
5.5 3.0 4.5
11 12 13
10.5 11.5 12.5
Output: 155 148.5
Private
Input:
3.14 3.15 3.15
10 20 30
10.11 11.11 12.11
Output: 188.9 104.888
Answer:
LINE-1: template<typename T, typename U>
Or
LINE-1: template<class T, class U>
LINE-2: std::vector<T>& v1, std::vector<U>& v2
LINE-3: typedef decltype(v1[0] * v2[0]) Tmp
Explanation:
At LINE-1 the appropriate template can be defined as:
template<typename T, typename U>
or template<class T, class U>
At LINE-2 the header for function inner product can be written as:
void inner product(std::vector<T>& v1, std::vector<U>& v2)
At LINE-3 the new type Tmp can be created as:
typedef decltype(v1[0] * v2[0]) Tmp
16