Assignment 11 Solution
Assignment 11 Solution
Total Marks : 27
Question 1
Consider the program (in C++11) given below. [MSQ, Marks 2]
#include <iostream>
class A {
public:
A(const int& n) { std::cout << "base - lvalue : " << n << std::endl; }
A(int&& n) { std::cout << "base - rvalue : " << n << std::endl; }
};
class B {
public:
template<typename T, typename U>
B(T&& n1, U&& n2) : ____________________ { } //LINE-1
private:
A a1_, a2_;
};
int main(){
int i = 10;
B b1(i, 20);
return 0;
}
Choose the appropriate option to fill in the blank at LINE-1 so that the output becomes
base - lvalue : 10
base - rvalue : 20
Answer: b), c)
Explanation:
1
From the output we can understand that for object a1 the l-value version of the constructors
and for object a2 the r-value version of the constructors need to be called. Since at the con-
structor of class B, n1 and n2 are received as universal reference types, n1 can be forwarded to
class A constructor as a1 (n1) or as a1 (std::forward<T>(n1)) but n1 needs to be forwarded
to class A constructor as a1 (std::forward<T>(n2))
2
Question 2
Consider the code segment (in C++11) given below. [MSQ, Marks 2]
template<typename T>
class TestData{
public:
void fun1(T&& n); //LINE-1
template<typename U>
void fun2(U&& n); //LINE-2
void fun3(TestData&& n); //LINE-3
template<typename V>
void fun4(std::vector<V>&& n); //LINE-4
};
a) LINE-1
b) LINE-2
c) LINE-3
d) LINE-4
Answer: b)
Explanation:
Note that && usually indicates rvalue reference. && indicates a universal reference only where
type deduction takes place.
At LINE-1, no type deduction takes place during function call (the type deduction takes place
during class instantiation), therefore && at LINE-1 is just a rvalue reference, not a universal
reference.
At LINE-2, the template type parameter U requires type deduction. Thus, && at LINE-2
indicates a universal reference.
At LINE-3, requires no type deduction. Thus, && at LINE-3 indicates a rvalue reference.
At LINE-4, the template type parameter V requires type deduction. However, since the form of
function parameter is not V&& (it in form std::vector<V>&&), it indicates only rvalue reference.
Intentionally kept as MSQ
3
Question 3
Consider the following code segment (in C++11). [MSQ, Marks 2]
#include <iostream>
int main() {
if(isPlatinum(CCType::PLATINUM) && isGold(CCType::GOLD) && isSilver(CCType::SILVER))
std::cout << "true";
return 0;
}
Identify the statement/s which are true for the given program.
Answer: b), c)
Explanation:
The statement if(col == CCType::SILVER) compares between two CCType type elements,
which compiles successfully.
The statement if(col == METAL::GREEN) compares between CCType type with METAL type,
which are not type castable. Thus it generates error.
The statement if(col == PLATINUM) compares between CCType type with int, which are not
type castable. Thus it generates error.
Since the code generates compiler error, it will not produce any output.
4
Question 4
Consider the following code segment (in C++11). [MCQ, Marks 2]
#include <iostream>
#include <algorithm>
#include <vector>
int main() {
std::vector<int> iVec {20, 40, 60, 10, 50};
/* code-block-1 */
sort(iVec.begin(), iVec.end(), compare());
for(int i : iVec)
std::cout << i << " ";
return 0;
}
Identify the appropriate code block to be placed at code-block-1 such that the output is 60
50 40 20 10 .
b) struct compare{
bool operator()(int a, int b){ return a > b; }
};
c) class compare{
bool operator()(int a, int b){ return a > b; }
};
Answer: b)
Explanation:
A functor can be local to a function; however, it is not possible for a function or class. Therefore,
b) is the correct option.
5
Question 5
Consider the following code segment (in C++11). [MSQ, Marks 2]
#include <iostream>
template<typename T>
class Data{
public:
Data() = delete;
Data(T _i) : i(_i){ }
Data(const Data& ) = delete;
Data(Data&& ) = default;
private:
T i;
};
int main(){
Data<int> d1; //LINE-1
Data<int> d2(30); //LINE-2
Data<int> d3 = d2; //LINE-3
Data<int> d4 = std::move(d2); //LINE-4
return 0;
}
a) LINE-1
b) LINE-2
c) LINE-3
d) LINE-4
Answer: a), c)
Explanation:
Since the default constructor and the copy constructor of class Data are explicitly deleted.
LINE-1 and LINE-3m generate compiler errors.
6
Question 6
Consider the following code segment (in C++11). [MCQ, Marks 2]
#include <iostream>
class emp{
public:
explicit emp() : emp(0) { std::cout << "#1 "; } //LINE-1
explicit emp(const int i) : emp(i, dSalary) { std::cout << "#2 "; } //LINE-2
explicit emp(const double s) : emp(0, s) { std::cout << "#3 "; } //LINE-3
emp(int i, double s) : id_{i}, salary_{s} { std::cout << "#4 ";} //LINE-4
private:
int id_ { -1 };
double salary_ { 0.0 };
static constexpr double dSalary = 10000.00;
};
int main(){
emp e1;
return 0;
}
a) #1
b) #2 #1
c) #4 #2 #1
d) #1 #2 #4
Answer: c)
Explanation:
The instatiation of object as emp e1; causes the follwoing consecutive calls to the constrcutors:
1. constructor at LINE-1,
2. constructor at LINE-2,
3. constructor at LINE-4.
Since the constructors are executed in reverse order of the calls, the output would be #4 #2
#1 .
7
Question 7
Consider the following program (in C++14). [MCQ, Marks 2]
#include <iostream>
a) 254, 254
b) 10000, 10000
c) 10000, 254
d) 254, 10000
Answer: c)
Explanation:
In the expression: [](auto(cm)) return cm * cvrt<decltype(cm)>; (100) , the inferred
type of cm is int. So, the result is 10000.
In the expression: [](auto(cm)) return cm * cvrt<decltype(cm)>; (100.0) , the in-
ferred type of cm is double. So, the result is 254.
8
Question 8
Consider the following λ expression (in C++11). [MCQ, Marks 2]
Identify the most appropriate option that define the equivalent closure object for the above
lambda function.
a) struct stat_closure {
int d;
int& sum;
stat_closure(int d_, int& sum_) : d(d_), sum(sum_) { }
void operator()(std::list<int> l, double& avg) const {
for(auto i : l)
sum += i;
avg = (double)sum / l.size();
}
};
auto stat = stat_closure(d, sum);
b) struct stat_closure {
int d;
int sum;
stat_closure(int d_, int& sum_) : d(d_), sum(sum_) { }
operator()(std::list<int> l) {
for(auto i : l)
sum += i;
return (double)sum / l.size();
}
};
auto stat = stat_closure(d, sum);
c) struct stat_closure {
int d;
int sum;
stat_closure(int d_, int& sum_) : d(d_), sum(sum_) { }
double operator()(std::list<int> l) const {
for(auto i : l)
sum += i;
return (double)sum / l.size();
}
};
auto stat = stat_closure(d, sum);
d) struct stat_closure {
int d;
int& sum;
stat_closure(int d_, int& sum_) : d(d_), sum(sum_) { }
double operator()(std::list<int> l) const {
9
for(auto i : l)
sum += i;
return (double)sum / l.size();
}
};
auto stat = stat_closure(d, sum);
Answer: d)
Explanation:
For a λ-expression, the compiler creates a functor class with:
• data members:
• a public inline const function call operator() with the parameters of the lambda as
parameters, generated from the body of the lambda
10
Question 9
Consider the following code segment (in C++11). [MSQ, Marks 2]
#include <iostream>
#include <string>
class intData {
public:
intData(bool data) : d1_(data) { }
intData(std::string data) : d2_(data) { }
private:
bool d1_ { false };
std::string d2_ { "" };
};
int main(){
std::string v = "false";
intData i1(true);
intData i2(v);
std::cout << i1 << " "; //LINE-1
std::cout << (bool)i2 << " "; //LINE-2
std::cout << static_cast<bool>(i1) << " "; //LINE-3
std::cout << bool(i2) << " "; //LINE-4
return 0;
}
a) LINE-1
b) LINE-2
c) LINE-3
d) LINE-4
Answer: a)
Explanation:
Since the typecast (to bool) operator is overloaded at LINE-1 is explicit, the typecast to bool
must an explicit typecasting. LINE-1 has an implicit which causes compiler error. The rest of
the options are explicit typecasting.
Intentionally kept as MSQ
11
Programming Questions
Question 1
Consider the following program (in C++11).
• Fill in the blanks at LINE-1 and LINE-3 with appropriate template definitions.
• Fill in the blanks at LINE-2 and LINE-4 with appropriate parameters for findMax func-
tion.
The program must satisfy the sample input and output. Marks: 3
#include <iostream>
_____________________ //LINE-1
double findMax(__________________){ return num; } //LINE-2
_____________________ //LINE-3
double findMax(__________________){
return num >= findMax(nums...) ? num : findMax(nums...); //LINE-4
}
int main(){
int a, b, c;
double d, e, f;
std::cin >> a >> b >> c;
std::cin >> d >> e >> f;
std::cout << findMax(a, b, c) << " ";
std::cout << findMax(d, e, f) << " ";
std::cout << findMax(a, b, c, d, e, f);
return 0;
}
Public 1
Input:
10 20 30
12.5 15.5 20.5
Output:
30 20.5 30
Public 2
Input:
1 5 3
2.3 6.7 2.1
Output:
5 6.7 6.7
Private
Input:
400 30 100
10.65 100.56 200.43
12
Output:
400 200.43 400
Answer:
LINE-1: template <typename T>
LINE-2: T num
LINE-3: template <typename T, typename... Tail>
LINE-4: T num, Tail... nums
Explanation:
At LINE-1, the definition of the simple template is:
template <typename T>
, and at LINE-3 the parameter of the function findMax are:
T num
At LINE-3, the definition of the veriadic template is:
template <typename T, typename... Tail>
, and at LINE-4 the parameters of the function findMax are:
T num, Tail... nums
13
Question 2
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 declaration for the function
wrapper.
• Fill in the blank at LINE-2 with an appropriate header for function wrapper.
• Fill in the blank at LINE-3 with an appropriate return statement for function wrapper.
The program must satisfy the sample input and output. Marks: 3
#include <iostream>
#include <vector>
____________________________________________ //LINE-1
__________________________________________ { //LINE-2
_______________________________________; //LINE-3
}
int main() {
std::vector<int> iv;
std::vector<double> dv;
for(int i = 0; i < 3; i++){
int a;
std::cin >> a;
iv.push_back(a);
}
for(int i = 0; i < 3; i++){
double b;
std::cin >> b;
dv.push_back(b);
14
}
Public 1
Input:
10 20 30
1.5 2.5 2.5
Output:
lvalue version: 66.5
rvalue version: 66.5
Public 2
Input:
1 -3 -4
2.5 4.5 -3
Output:
lvalue version: -2
rvalue version: -2
Private
Input:
43 12 6
10.5 3.6 -98.3
Output:
lvalue version: -23.2
rvalue version: -23.2
Answer:
LINE-1: template<typename F, typename... T>
Or
LINE-1: template<class F, class... T>
LINE-2: auto wrapper(std::ostream& os, F&& func, T&&... args) -> decltype(func(os,
args...)) in C++11.
Or
LINE-2: decltype(auto) wrapper(std::ostream& os, F&& func, T&&... args) in C++14.
LINE-3: return func(os, std::forward<T>(args)...)
Explanation:
At LINE-1 the template for function wrapper can be declared as:
template<typename F, typename... T>
Or
template<class F, class... T>
At LINE-2 header for function wrapper can be written as:
auto wrapper(std::ostream& os, F&& func, T&&... args) -> decltype(func(os, args...))
in C++11.
15
Or
decltype(auto) wrapper(std::ostream& os, F&& func, T&&... args) in C++14.
At LINE-3 the return statement should be:
return func(os, std::forward<T>(args)...)
16
Question 3
Consider the following program (in C++11) to find factorials of 3 integers. Fill in the blanks
as per the instructions given below:
• Fill in the blank at LINE-1 to complete the λ function for computing factorial.
• Fill in the blank at LINE-2 to complete the λ function for printing the vector v2.
The program must satisfy the sample input and output. Marks: 3
#include <iostream>
#include <functional>
#include <vector>
int main() {
std::vector<int> v1;
std::vector<long long> v2;
_________________________________________________ { //LINE-1
return n > 1 ? n * fact(n - 1) : 1;
};
for(auto i : v1)
v2.push_back(fact(i));
_________________________________________________ { //LINE-2
for (auto i : x){ std::cout << i << " "; } }(v2);
return 0;
}
Public 1
Input: 2 3 4
Output: 2 6 24
Public 2
Input: 1 3 5
Output: 1 6 120
Private
Input: 2 4 6
Output: 2 24 720
Answer:
LINE-1: const std::function<long long(int)> fact = [&fact](int n)
17
LINE-2: [](std::vector<long long> x)
Explanation:
The λ function for computing the factorial can be written as:
[](std::vector<long long> x) { for (auto i : x){ std::cout << i << " "; } }(v2);
18