Home > OS >  Valid Objects for a template argument
Valid Objects for a template argument

Time:11-11

Consider the following code :

  template <class T>
    T average(T *atArray, int nNumValues)
    {
        T tSum = 0;
        for (int nCount = 0; nCount < nNumValues; nCount  )
        {
            tSum  = atArray[nCount];
        }
        tSum = tSum / nNumValues;
        return tSum;

}

And the following question on it :

Which of the following statements about the class/type T must be true in order for the code to compile and run without crashing?

  1. It must be some kind of numeric type
  2. Must have < operator-defined
  3. Must have the [ ] access operator-defined
  4. Must have copy constructor and assignment operator



My Thoughts:
I think it could be something apart from numeric type but it will need to have the operator and / well defined.
point 2 seems incorrect as < has no relation with / and operator
same with point 3 and point 4.
Although I am not sure about my reasoning above.

CodePudding user response:

  1. No - It could for example do implicit conversions to/from a numeric type and have operator = defined.
  2. No - That operator is not used on a T
  3. No - That operator is not used on a T, only a T* and pointer types all have this operator defined.
  4. No - The copy constructor can be deleted and the question says "and" so the answer is no. It needs some kind of assignment operator though.

Consider this class, especially constructed to be able to answer no to as many questions as possible:

struct foo {
    foo() = default;
    foo(int) {}                                   // implicit conversion from int
    
    foo(const foo&) = delete;                     // no copy constructor
    foo(foo&&) = default;                         // but move constructor
    foo& operator=(const foo&) = delete;          // no copy assignment
    foo& operator=(foo&&) = delete;               // no move assignment
    
    foo& operator=(int) { return *this; };        // but assignment from int

    foo& operator =(const foo&) { return *this; } // for tSum  = atArray[nCount];

    operator int() const { return 1; }            // implicit conversion to int
};

And it would work fine with the function template:

int main() {
    foo arr[2];

    auto x = average(arr, 2);
}

CodePudding user response:

  1. A class type with sufficient overloaded operators (like std::complex<double>) could work.
  2. The < is only used on int expressions, not involving T.
  3. The atArray[nCount] expression uses a T* pointer, not an expression with type T, so it has the built-in meaning.
  4. Technically no, since fundamental types don't have constructors or assignment operators at all, just similar semantics. Also, technically every class type "has" a copy constructor and assignment operator, even if deleted. Another issue: T could be a class with normal assignment operator, deleted copy constructor, and public non-deleted move constructor.

Probably the intended answer is #4.

The actual requirements on T are:

  1. A variable of type T can be copy-initialized from an int, or from a null pointer constant. (0 is a special expression which can do two different things...)
  2. T is a numeric type, or an enumeration or class type with valid operator functions supporting expressions:
    1. a = b and a = b, where a and b are lvalues of type T
    2. a / n, where a is an lvalue of type T and n is an lvalue of type int
  3. T is move-constructible.
  •  Tags:  
  • c
  • Related