C++ Function Quiz

C++
0 Passed
0% acceptance

40 in-depth questions covering C++ function fundamentals including declaration, parameters, overloading, passing mechanisms, and inline functions — with 10 code examples to solidify understanding.

40 Questions
~80 minutes
1

Question 1

When designing a function that must modify its input parameters and return multiple values, what parameter passing mechanism provides the most efficient and clear implementation?

cpp
#include <iostream>

void processData(int& input, int& output1, int& output2) {
    input *= 2;  // Modify input
    output1 = input + 10;
    output2 = input * 3;
}

int main() {
    int value = 5, result1, result2;
    processData(value, result1, result2);
    std::cout << value << " " << result1 << " " << result2;
    return 0;
}
A
Pass-by-reference with non-const references for input/output parameters, combined with return value for primary result
B
Pass-by-value for all parameters since it's simpler and avoids pointer syntax complications
C
Pass-by-pointer for all modifiable parameters to make the intent explicitly clear through pointer syntax
D
Global variables to share state between functions, eliminating the need for parameter passing entirely
2

Question 2

In a function that performs complex calculations on large objects, what return mechanism avoids unnecessary copying while maintaining type safety?

cpp
#include <vector>
#include <iostream>

std::vector<int> createLargeVector() {
    std::vector<int> result;
    for(int i = 0; i < 1000000; ++i) {
        result.push_back(i);
    }
    return result;  // Move semantics avoid copying
}

int main() {
    auto vec = createLargeVector();  // Efficient move, not copy
    std::cout << vec.size();
    return 0;
}
A
Return by value with move semantics for large objects, or return by reference for existing objects with proper lifetime management
B
Always return by pointer to avoid copying, with caller responsible for memory management
C
Return by value for all cases since modern compilers optimize away copies through RVO
D
Use global variables to store results, eliminating return value overhead entirely
3

Question 3

When implementing overloaded functions that handle different numeric types with similar logic, what design approach provides the most maintainable and extensible code?

cpp
#include <iostream>

// Function template for any arithmetic type
template<typename T>
T calculate(T a, T b) {
    return (a + b) * 2;
}

// Specialization for int
int calculate(int a, int b) {
    return (a + b) * 2 + 1;  // Special logic for integers
}

int main() {
    std::cout << calculate(3.5, 2.1) << " ";  // Uses template
    std::cout << calculate(3, 2);       // Uses specialization
    return 0;
}
A
Function templates that work with any arithmetic type, reducing code duplication while maintaining type safety
B
Separate overloaded functions for each numeric type to provide specialized implementations when needed
C
Single function with void* parameters and runtime type checking for maximum flexibility
D
Global functions with type-specific names instead of overloading to avoid resolution complexity
4

Question 4

In a performance-critical function that is called frequently with small data, what inline directive provides the best balance between performance and code size?

cpp
#include <iostream>

inline int fastMultiply(int a, int b) {
    return a * b;  // Simple operation, good for inlining
}

int main() {
    int result = 0;
    for(int i = 0; i < 1000000; ++i) {
        result += fastMultiply(i, 2);  // May be inlined
    }
    std::cout << result;
    return 0;
}
A
Inline keyword for small, frequently called functions where call overhead elimination outweighs code size increase
B
Never use inline since modern compilers make better inlining decisions than programmers
C
Always use inline for any function that could benefit from inlining, regardless of size
D
Use macros instead of inline functions for maximum performance and zero call overhead
5

Question 5

When designing a function that must work with both const and non-const objects, what overloading pattern provides the most intuitive interface?

cpp
#include <iostream>
#include <vector>

class Container {
    std::vector<int> data;
public:
    // Const version for reading
    const int& get(size_t index) const {
        return data[index];
    }
    // Non-const version for modification
    int& get(size_t index) {
        return data[index];
    }
};

int main() {
    Container c;
    const Container& constRef = c;
    constRef.get(0);  // Calls const version
    c.get(0);         // Calls non-const version
    return 0;
}
A
Const and non-const overloads where the const version returns const references and the non-const version returns non-const references
B
Single function with const_cast to remove constness when needed, simplifying the interface
C
Two separate functions with different names to avoid overloading complexity
D
Always use non-const parameters since const-correctness is overrated for function interfaces
6

Question 6

Consider this function overloading scenario. Which function will be called when we invoke add(5, 3.14)?

cpp
#include <iostream>

int add(int a, int b) {
    return a + b;
}

double add(double a, double b) {
    return a + b;
}

int main() {
    auto result = add(5, 3.14);
    return 0;
}
A
The double add(double, double) function is called due to better type match for the floating-point literal
B
The int add(int, int) function is called with 3.14 truncated to 3 due to exact match for first parameter
C
Compilation fails due to ambiguous overload resolution between int and double versions
D
The function call is ambiguous and requires explicit casting to resolve
7

Question 7

In a function that processes a large container by reference to avoid copying, what const qualification provides the most safety and flexibility?

cpp
#include <vector>
#include <iostream>

void printSize(const std::vector<int>& container) {
    std::cout << container.size();  // Can read, not modify
}

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};
    printSize(vec);  // Efficient, no copy
    return 0;
}
A
Const reference parameter (const std::vector<int>&) allows reading without copying while preventing modification
B
Non-const reference for maximum flexibility since the function might need to modify the container
C
Pass by value since modern move semantics make copying efficient for large objects
D
Pointer parameter with const correctness to explicitly show the function won't modify the data
8

Question 8

When implementing a function that must return a reference to an internal static object, what considerations affect the design and safety?

cpp
#include <iostream>
#include <string>

const std::string& getDefaultName() {
    static std::string defaultName = "Default";  // Static lifetime
    return defaultName;  // Safe to return reference
}

int main() {
    const std::string& name = getDefaultName();  // Valid reference
    std::cout << name;
    return 0;
}
A
Static local variables can be returned by reference safely since they persist for program lifetime, but thread safety must be considered
B
Never return references to local variables since they become dangling references when the function returns
C
Return by value instead of reference to avoid lifetime issues with local variables
D
Use dynamic allocation and return a pointer, with caller responsible for deallocation
9

Question 9

In a function template that must handle both lvalue and rvalue arguments efficiently, what parameter type provides the most flexible and optimized implementation?

cpp
#include <iostream>
#include <vector>

// Universal reference template
function template<typename T>
void process(T&& arg) {
    std::cout << "Processing: " << arg << std::endl;
}

int main() {
    int x = 42;
    process(x);        // lvalue reference
    process(42);       // rvalue reference
    process(std::move(x));  // rvalue reference
    return 0;
}
A
Universal reference (T&&) with perfect forwarding to preserve value category and enable move semantics
B
Const reference (const T&) for all cases since it accepts both lvalues and rvalues
C
Pass by value (T) to always get a copy that can be modified without affecting the original
D
Pointer parameter (T*) requiring callers to pass addresses explicitly
10

Question 10

When designing overloaded operators as functions, what naming convention and parameter patterns provide the most intuitive usage?

cpp
#include <iostream>

class Complex {
    double real, imag;
public:
    Complex(double r, double i) : real(r), imag(i) {}
    // Member operator for asymmetric operations
    Complex operator+(const Complex& other) const {
        return Complex(real + other.real, imag + other.imag);
    }
};

// Global operator for symmetric operations
Complex operator*(const Complex& a, const Complex& b) {
    return Complex(a.real * b.real - a.imag * b.imag,
                   a.real * b.imag + a.imag * b.real);
}

int main() {
    Complex c1(1, 2), c2(3, 4);
    auto sum = c1 + c2;    // Member operator
    auto prod = c1 * c2;   // Global operator
    return 0;
}
A
operator+ as a member function for binary operators, taking one parameter for the right operand
B
Global operator functions for symmetric operators, taking two parameters for left and right operands
C
Regular named functions like add() instead of operator overloading to avoid confusion
D
Macros for operator-like functionality to avoid function call overhead
11

Question 11

In a recursive function that processes tree structures, what parameter passing mechanism prevents unnecessary copying while maintaining safety?

cpp
#include <iostream>

struct Node {
    int value;
    Node* left;
    Node* right;
};

int sumTree(const Node* node) {  // Const pointer prevents modification
    if (!node) return 0;
    return node->value + sumTree(node->left) + sumTree(node->right);
}

int main() {
    // Tree structure would be built here
    return 0;
}
A
Const reference for the tree node to avoid copying large structures while preventing modification
B
Pass by value since recursive functions typically work with small data structures
C
Raw pointers for maximum performance and ability to modify the tree structure
D
Global variables to share tree state across recursive calls
12

Question 12

When implementing a function that must handle variable numbers of arguments, what modern C++ feature provides the most type-safe and flexible solution?

cpp
#include <iostream>

// Variadic template function
template<typename... Args>
void printAll(Args... args) {
    // Fold expression for printing
    (std::cout << ... << args) << std::endl;
}

int main() {
    printAll(1, " ", 3.14, " ", "hello");  // Any number of arguments
    return 0;
}
A
Variadic templates with parameter packs for compile-time type safety and perfect forwarding
B
Va_list and va_arg from C standard library for runtime argument processing
C
Overloaded functions with different parameter counts for each possible argument combination
D
Single function with std::vector parameter to collect all arguments
13

Question 13

In a function that performs computation on fundamental types, what inline specification provides the best performance characteristics?

cpp
#include <iostream>

inline double fastSqrt(double x) {
    // Complex mathematical computation
    double result = x;
    for(int i = 0; i < 10; ++i) {
        result = 0.5 * (result + x / result);
    }
    return result;
}

int main() {
    double val = fastSqrt(16.0);  // May or may not be inlined
    std::cout << val;
    return 0;
}
A
Inline specifier for small functions where call overhead dominates execution time
B
No inline specifier, letting the compiler decide based on optimization level and function characteristics
C
Always inline for any function that could potentially benefit from inlining
D
Use macros instead of functions for guaranteed inlining and performance
14

Question 14

When designing a function that must return different types based on input parameters, what language feature provides the most elegant solution?

cpp
#include <iostream>
#include <type_traits>

// Function template with auto return type deduction
auto process(int x) {
    if (x > 0) return x * 2;      // Returns int
    else return x * 2.0;         // Returns double
}

int main() {
    auto result1 = process(5);   // int
    auto result2 = process(-3);  // double
    return 0;
}
A
Function templates with auto return type deduction for compile-time type resolution
B
Void return type with output parameters modified by reference
C
Runtime type identification with dynamic casting for return type determination
D
Separate functions with different names for each return type combination
15

Question 15

In a function that modifies a container through a reference parameter, what const considerations affect the interface design?

cpp
#include <vector>
#include <iostream>

void addElement(std::vector<int>& container) {  // Non-const reference
    container.push_back(42);  // Modifies container
}

void printSize(const std::vector<int>& container) {  // Const reference
    std::cout << container.size();  // Only reads
}

int main() {
    std::vector<int> vec;
    addElement(vec);    // Can modify
    printSize(vec);     // Can only read
    return 0;
}
A
Non-const reference parameter clearly indicates the function will modify the container, enabling optimization
B
Const reference to prevent accidental modification while still allowing efficient access
C
Pass by value to ensure the function gets its own copy to modify freely
D
Pointer parameter with explicit documentation about modification behavior
16

Question 16

Consider this function with default parameters. What happens when we call print(10)?

cpp
#include <iostream>

void print(int x, int y = 20, int z = 30) {
    std::cout << x << " " << y << " " << z << std::endl;
}

int main() {
    print(10);
    return 0;
}
A
Program prints '10 20 30' using default values for y and z since they were not provided
B
Program prints '10 0 0' because default parameters are initialized to zero if not specified
C
Compilation fails because default parameters must be provided in function calls
D
Program prints '10 20 30' but with a warning about missing parameters
17

Question 17

When implementing a function that must handle both success and error cases, what return type pattern provides the most expressive error handling?

cpp
#include <iostream>
#include <optional>

std::optional<int> safeDivide(int a, int b) {
    if (b == 0) return std::nullopt;  // Error case
    return a / b;  // Success case
}

int main() {
    auto result = safeDivide(10, 2);
    if (result) {
        std::cout << *result;  // 5
    } else {
        std::cout << "Division by zero";
    }
    return 0;
}
A
std::optional or std::expected for functions that may fail, providing type-safe error indication
B
Bool return type with output parameters for error information and results
C
Int return type with special values (like -1) to indicate errors
D
Void return type with exceptions for error cases
18

Question 18

In a function template that must constrain its parameters to specific types, what C++ feature provides the most readable and maintainable constraints?

cpp
#include <iostream>
#include <concepts>

// Function template with concepts
template<typename T>
requires std::integral<T>  // Only integral types
T factorial(T n) {
    T result = 1;
    for(T i = 2; i <= n; ++i) {
        result *= i;
    }
    return result;
}

int main() {
    std::cout << factorial(5);  // Works
    // factorial(3.14);  // Would fail to compile
    return 0;
}
A
Concepts (C++20) for clear, named requirements on template parameters
B
SFINAE with enable_if for complex type constraints and conditional compilation
C
Runtime type checking with dynamic_cast to validate template parameters
D
Separate template specializations for each supported type
19

Question 19

When designing a function that must be callable from C code, what declaration attributes ensure C linkage and calling convention compatibility?

cpp
#include <iostream>

// C-compatible function
extern "C" int cFunction(int x) {
    return x * 2;
}

// Regular C++ function
int cppFunction(int x) {
    return x * 3;
}

int main() {
    std::cout << cFunction(5) << " " << cppFunction(5);
    return 0;
}
A
Extern "C" declaration to prevent name mangling and ensure C-compatible calling convention
B
Inline specifier to ensure the function is available in header files for C inclusion
C
Static declaration to limit visibility and avoid linkage conflicts
D
Constexpr specifier for compile-time evaluation compatible with C compilers
20

Question 20

In a performance-critical mathematical function that is called in tight loops, what combination of features provides the best optimization opportunities?

cpp
#include <iostream>

// Constexpr for compile-time evaluation when possible
constexpr double fastPower(double base, int exp) {
    double result = 1.0;
    for(int i = 0; i < exp; ++i) {
        result *= base;
    }
    return result;
}

int main() {
    constexpr double compileTime = fastPower(2.0, 3);  // Compile-time
    double runtime = fastPower(2.0, 3);               // Runtime
    std::cout << compileTime << " " << runtime;
    return 0;
}
A
Inline function with constexpr where possible, allowing compile-time evaluation when arguments are constant
B
Regular function with aggressive compiler optimization flags for automatic inlining
C
Macro definition instead of function for guaranteed inlining and zero overhead
D
Virtual function for runtime polymorphism and optimization through dynamic dispatch
21

Question 21

When implementing overloaded functions for a math library that must handle different precision levels, what design pattern provides the most intuitive user experience?

cpp
#include <iostream>
#include <cmath>

// Overloaded functions for different precisions
double sin(double x) { return std::sin(x); }
float sin(float x) { return std::sinf(x); }
long double sin(long double x) { return std::sinl(x); }

int main() {
    double d = sin(1.0);    // Calls double version
    float f = sin(1.0f);    // Calls float version
    std::cout << d << " " << f;
    return 0;
}
A
Overloaded functions with same name but different parameter types (float, double, long double) for seamless precision selection
B
Separate functions with precision suffixes (sinf, sin, sinl) following C library conventions
C
Single template function with explicit type parameters for precision control
D
Runtime precision selection through configuration parameters
22

Question 22

In a function that processes a string by reference to avoid copying, what parameter type provides the most flexible and safe interface?

cpp
#include <iostream>
#include <string>

void processString(const std::string& str) {
    std::cout << "Length: " << str.length() << std::endl;
    // Cannot modify str here
}

int main() {
    std::string s = "Hello World";
    processString(s);        // lvalue
    processString("temp");  // rvalue
    return 0;
}
A
Const std::string& for read-only access that accepts both lvalues and rvalues efficiently
B
std::string&& for rvalue references to enable move semantics and avoid copying
C
std::string for pass-by-value with move semantics to handle all cases uniformly
D
const char* for C-style string compatibility and maximum flexibility
23

Question 23

When designing a function that must handle both mutable and immutable data structures, what overloading strategy provides the most comprehensive interface?

cpp
#include <iostream>
#include <vector>

class DataProcessor {
    std::vector<int> data;
public:
    // Const version for read-only access
    int getSum() const {
        int sum = 0;
        for(int val : data) sum += val;
        return sum;
    }
    // Non-const version for modification
    void addValue(int val) {
        data.push_back(val);
    }
};

int main() {
    DataProcessor dp;
    dp.addValue(5);           // Non-const call
    const DataProcessor& cdp = dp;
    std::cout << cdp.getSum();  // Const call
    return 0;
}
A
Const and non-const member function overloads for class methods, or const/non-const parameter overloads for free functions
B
Single function with mutable parameters that can be modified as needed
C
Two separate functions with different names for const and non-const cases
D
Runtime const checking with const_cast to remove constness when necessary
24

Question 24

In a function template that must handle containers of different types, what template parameter pattern provides the most flexible container access?

cpp
#include <iostream>
#include <vector>
#include <list>

// Template function for any container type
template<typename Container>
void printElements(const Container& container) {
    for(const auto& element : container) {
        std::cout << element << " ";
    }
    std::cout << std::endl;
}

int main() {
    std::vector<int> vec = {1, 2, 3};
    std::list<double> lst = {1.1, 2.2, 3.3};
    printElements(vec);  // Works with vector
    printElements(lst);  // Works with list
    return 0;
}
A
Template<typename Container> with iterator access for generic container support
B
Template<typename T> with std::vector<T> parameter for specific container requirements
C
Void* parameter with runtime type checking for maximum container flexibility
D
Multiple overloaded functions for each supported container type
25

Question 25

When implementing a function that must return a newly created object, what return mechanism provides the most efficient transfer of ownership?

cpp
#include <iostream>
#include <vector>

std::vector<int> createVector(int size) {
    std::vector<int> result;
    result.reserve(size);
    for(int i = 0; i < size; ++i) {
        result.push_back(i * 2);
    }
    return result;  // Move semantics transfer ownership
}

int main() {
    auto vec = createVector(1000000);  // Efficient move, not copy
    std::cout << vec.size();
    return 0;
}
A
Return by value with move semantics to enable efficient transfer without copying
B
Return by pointer with caller responsible for deallocation to avoid copy overhead
C
Return by reference to a local static object for efficiency and lifetime management
D
Use output parameter by reference to modify caller's object directly
26

Question 26

In a function that performs validation on input parameters, what early return pattern provides the most readable and maintainable error handling?

cpp
#include <iostream>
#include <stdexcept>

int divide(int a, int b) {
    if (b == 0) {
        throw std::invalid_argument("Division by zero");
    }
    return a / b;
}

// Or with early return:
int safeDivide(int a, int b) {
    if (b == 0) return 0;  // Early return on error
    return a / b;
}

int main() {
    try {
        std::cout << divide(10, 0);
    } catch (const std::exception& e) {
        std::cout << "Error: " << e.what();
    }
    return 0;
}
A
Early return on invalid input with clear error indication, reducing nesting and improving readability
B
Deep nesting with if-else chains to handle all validation cases in sequence
C
Single boolean flag that accumulates validation results throughout the function
D
Exceptions for all validation failures to centralize error handling outside the function
27

Question 27

When designing overloaded operators for a user-defined type, what implementation approach provides the most consistent and expected behavior?

cpp
#include <iostream>

class Point {
    int x, y;
public:
    Point(int x, int y) : x(x), y(y) {}
    // Member operator for asymmetric operations
    Point& operator+=(const Point& other) {
        x += other.x;
        y += other.y;
        return *this;
    }
};

// Global operator using member operator
Point operator+(Point lhs, const Point& rhs) {
    lhs += rhs;
    return lhs;
}

int main() {
    Point p1(1, 2), p2(3, 4);
    Point sum = p1 + p2;  // Uses global operator
    return 0;
}
A
Member functions for operators where the left operand is the class type, global functions for symmetric operators
B
Global functions for all operators to ensure consistency and avoid member function complications
C
Macros for operator definitions to ensure maximum performance and inlining
D
Named member functions instead of operators to avoid overloading complexity
28

Question 28

In a recursive function that processes hierarchical data, what parameter design prevents stack overflow while maintaining efficiency?

cpp
#include <iostream>

struct TreeNode {
    int value;
    TreeNode* left;
    TreeNode* right;
};

// Efficient recursive function
int sumTree(const TreeNode* node) {
    if (!node) return 0;
    return node->value + 
           sumTree(node->left) + 
           sumTree(node->right);
}

int main() {
    // Tree would be constructed here
    return 0;
}
A
Reference or pointer parameters to avoid copying large data structures on each recursive call
B
Pass by value for small data structures since recursion depth is typically limited
C
Global variables to share state across recursive calls and reduce parameter passing
D
Convert to iterative algorithm with explicit stack to avoid recursion depth limits
29

Question 29

When implementing a function that must handle both fundamental types and user-defined types efficiently, what template design provides the most optimized code generation?

cpp
#include <iostream>

// Template with specialization
template<typename T>
T process(T value) {
    return value * 2;  // General case
}

// Specialization for int
template<>
int process(int value) {
    return value * 2 + 1;  // Special logic for int
}

int main() {
    std::cout << process(3.5) << " ";  // Uses general template
    std::cout << process(3);           // Uses specialization
    return 0;
}
A
Function template with specialization for fundamental types to enable optimal code generation
B
Single generic function with runtime type checking for all cases
C
Overloaded functions for each supported type to provide hand-optimized implementations
D
Void* parameter with reinterpret_cast for maximum flexibility and performance
30

Question 30

In a function that must maintain state between calls without global variables, what design pattern provides the most encapsulated and thread-safe solution?

cpp
#include <iostream>

int counter() {
    static int count = 0;  // Static local variable
    return ++count;
}

int main() {
    std::cout << counter() << " ";  // 1
    std::cout << counter() << " ";  // 2
    std::cout << counter();         // 3
    return 0;
}
A
Static local variables within the function for persistent state with function scope
B
Reference parameters to external state objects managed by the caller
C
Global variables with proper synchronization for thread-safe state management
D
Member variables in a class with the function as a static method
31

Question 31

When designing a function that must handle variable argument counts with type safety, what C++ feature provides the most robust implementation?

cpp
#include <iostream>

// Variadic template with fold expression
template<typename... Args>
auto sum(Args... args) {
    return (args + ...);  // Fold expression
}

int main() {
    std::cout << sum(1, 2, 3, 4, 5);  // Any number of int args
    return 0;
}
A
Parameter pack expansion in variadic templates for compile-time type safety and perfect forwarding
B
std::initializer_list for homogeneous argument types with container semantics
C
Va_list from C standard library for runtime argument processing with type safety
D
Overloaded functions with increasing parameter counts for each possible argument combination
32

Question 32

Consider this inline function definition. What happens when this code is compiled and the function is called?

cpp
#include <iostream>

inline int square(int x) {
    return x * x;
}

int main() {
    int result = square(5);
    std::cout << result;
    return 0;
}
A
The multiplication x * x may be inlined directly at the call site, avoiding function call overhead
B
The inline keyword forces inlining regardless of compiler optimization settings
C
Inline functions cannot be defined in the same file where they are used
D
The function will always be called normally since inlining is deprecated in modern C++
33

Question 33

In a function that must return a reference to one of its parameters based on a condition, what reference qualification ensures lifetime safety?

cpp
#include <iostream>
#include <string>

// Function returning reference to parameter
const std::string& longerString(const std::string& a, const std::string& b) {
    return a.length() > b.length() ? a : b;
}

int main() {
    std::string s1 = "short", s2 = "much longer string";
    const std::string& result = longerString(s1, s2);
    std::cout << result;  // Safe reference to s2
    return 0;
}
A
Return reference with same const qualification as the selected parameter to maintain lifetime guarantees
B
Always return const reference to prevent modification of the returned object
C
Return by value to avoid lifetime issues with parameter references
D
Use pointers instead of references for return values to make lifetime explicit
34

Question 34

When implementing a function template that must handle both copyable and movable types efficiently, what parameter type provides the most optimized implementation?

cpp
#include <iostream>
#include <vector>

// Universal reference template
function template<typename T>
void process(T&& arg) {
    std::cout << "Value: " << arg << std::endl;
}

int main() {
    int x = 42;
    process(x);           // lvalue: copies
    process(42);          // rvalue: moves
    process(std::move(x)); // rvalue: moves
    return 0;
}
A
Universal reference (T&&) with std::forward for perfect forwarding of value categories
B
Const reference (const T&) for all cases since it accepts both lvalues and rvalues
C
Pass by value (T) to always get a copy that can be moved from if needed
D
Pointer parameter (T*) requiring explicit address-taking by callers
35

Question 35

In a function that performs complex computation with intermediate results, what return type deduction provides the most maintainable implementation?

cpp
#include <iostream>
#include <vector>

// Auto return type deduction
auto computeResult(int x, double y) {
    auto intermediate = x * 2.0;
    auto result = intermediate + y;
    return result;  // Returns double
}

int main() {
    auto value = computeResult(5, 3.14);
    std::cout << value;
    return 0;
}
A
Auto return type deduction (auto function() -> decltype(complex_expression)) for complex return types
B
Explicit return type specification to make function signature clear to callers
C
Void return with output parameters for all computed results
D
Template return type with explicit instantiation for different result types
36

Question 36

When designing overloaded functions for arithmetic operations on user-defined types, what parameter passing convention provides the most intuitive and efficient implementation?

cpp
#include <iostream>

class Matrix {
    // Matrix implementation
public:
    Matrix operator+(const Matrix& other) const;  // Member
};

Matrix operator*(const Matrix& a, const Matrix& b);  // Global

int main() {
    Matrix m1, m2, m3;
    Matrix sum = m1 + m2;   // Natural syntax
    Matrix prod = m1 * m2;  // Also natural
    return 0;
}
A
Pass by value for small types, const reference for large types to balance efficiency and clarity
B
Always pass by reference to avoid copying overhead regardless of type size
C
Always pass by value since move semantics make copying efficient for all types
D
Use pointers for all parameters to make modification intent explicit
37

Question 37

In a function that must handle both success and failure cases with detailed error information, what return type provides the most expressive error handling?

cpp
#include <iostream>
#include <variant>
#include <string>

std::variant<int, std::string> divide(int a, int b) {
    if (b == 0) {
        return "Division by zero";  // Error case
    }
    return a / b;  // Success case
}

int main() {
    auto result = divide(10, 0);
    if (std::holds_alternative<std::string>(result)) {
        std::cout << std::get<std::string>(result);
    } else {
        std::cout << std::get<int>(result);
    }
    return 0;
}
A
std::variant with success and error types, or std::expected for clear success/failure indication
B
Int return type with negative values for errors and positive for success codes
C
Bool return with global error variable for detailed error information
D
Void return with exceptions for all error cases and success paths
38

Question 38

When implementing a function that must work with any callable object (function, lambda, functor), what parameter type provides the most flexible interface?

cpp
#include <iostream>
#include <functional>

void executeCallback(std::function<void(int)> callback) {
    callback(42);
}

void myFunction(int x) {
    std::cout << "Called with: " << x << std::endl;
}

int main() {
    executeCallback(myFunction);  // Function pointer
    executeCallback([](int x) {   // Lambda
        std::cout << "Lambda: " << x << std::endl;
    });
    return 0;
}
A
Template parameter or std::function for accepting any callable type with uniform interface
B
Function pointer for traditional function support with known signature
C
Void* with callback mechanism for maximum flexibility and performance
D
Overloaded functions for each callable type (function pointer, lambda, functor)
39

Question 39

In a function template that must handle containers with different value types, what concept or constraint provides the most readable type requirements?

cpp
#include <iostream>
#include <vector>
#include <list>

// Template with concepts (C++20)
template<typename Container>
requires std::ranges::range<Container>
void printContainer(const Container& c) {
    for (const auto& item : c) {
        std::cout << item << " ";
    }
    std::cout << std::endl;
}

int main() {
    std::vector<int> v = {1, 2, 3};
    printContainer(v);
    return 0;
}
A
Requires clause with standard concepts like std::ranges::range for clear container requirements
B
SFINAE with complex enable_if expressions for detailed type constraints
C
Runtime type checking with dynamic_cast to validate container types
D
Documentation comments specifying container requirements without compile-time enforcement
40

Question 40

When designing a function that must handle both compile-time and runtime constants efficiently, what combination of specifiers provides the most optimization opportunities?

cpp
#include <iostream>

// Constexpr function for compile-time evaluation
constexpr int factorial(int n) {
    int result = 1;
    for(int i = 2; i <= n; ++i) {
        result *= i;
    }
    return result;
}

int main() {
    constexpr int compileTime = factorial(5);  // Compile-time
    int runtime = factorial(5);               // Runtime
    std::cout << compileTime << " " << runtime;
    return 0;
}
A
Constexpr for compile-time evaluation when possible, with runtime fallback for dynamic values
B
Const for all constant parameters to prevent modification and enable optimization
C
Inline for guaranteed inlining and performance regardless of constant nature
D
Static for internal linkage and optimization of constant handling

QUIZZES IN C++