Search code examples
c++templatesfriend

C++ declaration of template parameter shadows template parameter error


I have the following C++ code which I am compiling as below:

#include <cstddef>
#include <cassert>
template<typename T, std::size_t N> struct A;
template<typename T> struct Base {
    T &operator [](std::size_t i);
private:
    template<typename T, std::size_t N> friend struct A;
    #if !defined(NDEBUG)
        size_t n;
    #endif
};
template<typename T, std::size_t N> struct A : public Base<T> {
    A();
private:
    friend class Base<T>;
    T a[N];
};
template<typename T, std::size_t N> inline A<T,N>::A() { n = N; }
template<typename T> inline T& Base<T>::operator [](std::size_t i) {
    assert(i < n);
    return ((A<T,1>*)this)->a[i];
}
int main() {
    A<int, 3> a3;
    a3[1] = 1;
}

compiled using:

g++ -std=c++17 -O2 -Wall -pedantic main.cpp && ./a.out

and gives the following 3 compiler errors:

*main.cpp:7:14: error: declaration of template parameter 'T' shadows template parameter
    7 |     template<typename T, std::size_t N> friend struct A;

main.cpp:4:10: note: template parameter 'T' declared here
    4 | template<typename T> struct Base {

main.cpp: In constructor 'A<T, N>::A()':
main.cpp:18:58: error: 'n' was not declared in this scope
   18 | template<typename T, std::size_t N> inline A<T,N>::A() { n = N; }*

Gone through other similar errors posted here, but could not get the idea much to fix it.


After following all your answers there is only one error now by fixing the code with all your suggestions.

#include <cstddef>
using namespace std;
template <typename, std::size_t N> struct A;
template <typename T> struct Base { // template inheritance, compiler errors
    T& operator [](std::size_t i);
private:
    template<typename, std::size_t N> friend struct A;
    size_t n;
};
template <typename T, std::size_t N> struct A : public Base<T> {
    A();
private:
    friend class Base<T>;
    T a[N];
};
template <typename T, std::size_t N> inline A<T,N>::A() { n = N; }
template <typename T> inline T& Base<T>::operator[](std::size_t i) {
    return ((A<T,1>*)this)->a[i];
}
int main() { A<int, 3> a; a[1] = 1; }

Error is:

main.cpp: In constructor 'A< <template-parameter-1-1>, N>::A()':
main.cpp:17:59: error: 'n' was not declared in this scope
17 | template <typename T, std::size_t N> inline A<T,N>::A() { n = N; }

Solution

  • You are using the same name i.e., typename T in the outer and inner template:

    Outer:

    template<typename T> struct Base {
    ...
    

    Inner:

        template<typename T, std::size_t N> friend struct A;
        #if !defined(NDEBUG)
    

    Change either one to fix this.

    Inner fixed:

        template<typename U, std::size_t N> friend struct A;
        #if !defined(NDEBUG)
    

    Additionally, there's another error here:

    template<typename T, std::size_t N> inline A<T,N>::A() { n = N; }
    

    n is undeclared if NDEBUG is not defined, so you might need to wrap this in #ifdef as well.