Search code examples
c++genericscompiler-errorsdereference

Disable compiler warning 2100 for generic method in a list class that may contain pointers or not


I am trying to make an ArrayList class in C++ as a learning experience. Similar to the Java ArrayList class it is a dynamic array, the internal array is called 'content'. Unlike in Java I wanted my ArrayList to be able to take pointers and non-pointers. But I am getting a problem, I am using std::is_pointer::value to check whether the generic type is a pointer within a number of functions. If it is a pointer the function will need to preform differently to if it was not a pointer. My example below shows my printAll() function which is meant to print every element in the array on separate lines. If the generic type is a pointer the method needs to dereference each element in the array before printing them.

   int main() {
        ArrayList<int> a = ArrayList<int>();
        a.add(1);
        a.add(2);
        a.add(3);
        a.printAll();
        cin.ignore();
    }

    #pragma warning(push)
    #pragma warning(disable : 2100)
    template<class T>
    void ArrayList<T>::printAll() {
        if (std::is_pointer<T>::value) {
            for (int i = 0; i < this->occupiedSize; i++) {
                cout << "[" << i << "] " << *this->content[i];
                cout << endl;
            }
        } else {
            for (int i = 0; i < this->occupiedSize; i++) {
                cout << "[" << i << "] " << this->content[i];
                cout << endl;
            }
        }
    }
    #pragma warning(pop)

On the line: cout << "[" << i << "] " << *this->content[i]; I am getting warnings: C2100: illegal indirection and C2088: '<<': illegal for class

I'm assuming this is because the list is not of a pointer type and therefore cannot be dereferenced with *. But in a non-pointer list, std::is_pointer::value should return false and the code in that block is never executed anyway so it shouldn't be a problem. Disabling the warning doesn't seem to help.

If I do:

int main() {
    ArrayList<int*> a = ArrayList<int*>();
    a.add(new int(1));
    a.add(new int(2));
    a.add(new int(3));
    a.printAll();
    cin.ignore();
}

It works totally fine. Any ideas how I can solve this problem or how I can better implement this functionality?

I am using windows 10, Microsoft Visual Studio (latest version I believe).


Solution

  • This issue here is that even though you would never enter

    if (std::is_pointer<T>::value) {
        for (int i = 0; i < this->occupiedSize; i++) {
            cout << "[" << i << "] " << *this->content[i];
            cout << endl;
        }
    }
    

    If T is a non pointer type the compiler will still compile that block of code. Since it has illegal syntax you get a compiler warning.

    In the upcoming C++17 you can use constexpr if which will remove the code from the compilation if the condition is not true.

    If you do not have access to a compiler that supports that feature then you will have to use SFINAE and have two overloads of the function. One for if T is a pointer type and one for when T is not a pointer type. That would look like

    template<class T, std::enable_if_t<typename std::is_pointer<T>::value>* = nullptr>
    void ArrayList<T>::printAll() {
        for (int i = 0; i < this->occupiedSize; i++) {
            cout << "[" << i << "] " << *this->content[i];
            cout << endl;
        }
    }
    
    template<class T, std::enable_if_t<typename !std::is_pointer<T>::value>* = nullptr>
    void ArrayList<T>::printAll() {
        for (int i = 0; i < this->occupiedSize; i++) {
            cout << "[" << i << "] " << this->content[i];
            cout << endl;
        }
    }