Error declaration of template parameter t shadows template parameter

Использование шаблонов при описании классов template C++ Решение и ответ на вопрос 2262951

boolc

1 / 1 / 0

Регистрация: 21.09.2017

Сообщений: 31

1

12.06.2018, 05:14. Показов 11760. Ответов 4

Метки нет (Все метки)


C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
mylist.h
template<typename T> class MyList
{
public:
    MyList();
    ~MyList();
    void push_back(T data);
   // void hello();
private:
 
    template<typename T> class Node
    {
    public:
        Node *nNext;
        T data;
        Node(T data = T(), Node *nNext = nullptr)
        {
            this->data = data;
            this->nNext = nNext;
        }
    };
    Node<T> *Head;
    int nodeCount; 
};
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
mylist.cpp
#include "mylist.h"
 
template<typename T>
MyList<T>::MyList()
{
    nodeCount = 0;
    Head = nullptr;
}
template<typename T>
MyList<T>::~MyList()
{
 
}
 
template<typename T>
void MyList<T>::push_back(T data)
{
    if(Head == nullptr)
    {
        Head = new Node<T>(data);
    }
    else
    {
        //...
    }
}

При компиляции возникает ошибка, в файле mylist.h:
«error : declaration of template parameter ‘T’ shadows template parameter»
qt 5, gcc 7.3.0
как обойти?

__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь



0



zss

Модератор

Эксперт С++

12641 / 10135 / 6102

Регистрация: 18.12.2011

Сообщений: 27,170

12.06.2018, 06:42

2

Лучший ответ Сообщение было отмечено boolc как решение

Решение

class Node надо вытащить наружу

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//mylist.h
   template<typename T> class Node
    {
    public:
        Node *nNext;
        T data;
        Node(T data = T(), Node *nNext = nullptr)
        {
            this->data = data;
            this->nNext = nNext;
        }
    };
template<typename T> class MyList
{
public:
    MyList();
    ~MyList();
    void push_back(T data);
   // void hello();
private:
 
 
    Node<T> *Head;
    int nodeCount; 
};



1



1 / 1 / 0

Регистрация: 21.09.2017

Сообщений: 31

08.07.2018, 17:02

 [ТС]

3

Цитата
Сообщение от zss
Посмотреть сообщение

class Node надо вытащить наружу

Спасибо.



0



Croessmah

Don’t worry, be happy

17781 / 10545 / 2036

Регистрация: 27.09.2012

Сообщений: 26,516

Записей в блоге: 1

08.07.2018, 17:25

4

Цитата
Сообщение от boolc
Посмотреть сообщение

«error : declaration of template parameter ‘T’ shadows template parameter»

В обоих шаблонах

C++
1
template<typename T> class MyList
C++
1
template<typename T> class Node

параметр имеет имя T. Об этом и пишет компилятор.

Достаточно просто поменять имя параметра в одном из шаблонов.

C++
1
2
3
4
5
6
7
8
9
10
11
    template<typename U> class Node
    {
    public:
        Node *nNext;
        U data;
        Node(U data = U(), Node *nNext = nullptr)
        {
            this->data = data;
            this->nNext = nNext;
        }
    };

Но что-то мне подсказывает, что Вам вообще не нужен шаблонный Node, достаточно простого:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private:
 
    class Node
    {
    public:
        Node *nNext;
        T data;
        Node(T data = T(), Node *nNext = nullptr)
        {
            this->data = data;
            this->nNext = nNext;
        }
    };
    Node *Head;
    int nodeCount; 
};



0



1 / 1 / 0

Регистрация: 21.09.2017

Сообщений: 31

08.07.2018, 19:32

 [ТС]

5

Надо подумать



0



I’m trying to make a graphics program, but I’m having a problem …
My code is the one:

main.cpp:

#include "point_2d.h"
#include <iostream>

int main()
{
    cge::point_2d p(5, 5);
    p.x = 6;
    std::cout << p.x << " " << p.y << std::endl;
    std::cin.get();
    return 0;
}

point_2d.h:

#ifndef POINT_2D_H
#define POINT_2D_H

namespace cge
{

    template<typename T>
    struct basic_point_2d
    {

        typedef T value_type;

        constexpr basic_point_2d() noexcept = default;

        constexpr basic_point_2d(const basic_point_2d&) noexcept = default;

        constexpr basic_point_2d& operator=(const basic_point_2d&) noexcept = default;

        template<typename U>
        constexpr explicit basic_point_2d(const basic_point_2d<U>&) noexcept; //Conversions

        constexpr basic_point_2d(T, T) noexcept; //Constructors

        constexpr bool equal(const basic_point_2d&) const noexcept;

        template<typename T>
        friend constexpr bool operator==(const basic_point_2d<T>&, const basic_point_2d<T>&) noexcept; 

        template<typename T>
        friend constexpr bool operator!=(const basic_point_2d<T>&, const basic_point_2d<T>&) noexcept;


        T x = T();
        T y = T();

    }; //struct basic_point_2d

    typedef basic_point_2d<int> point_2d;
    typedef basic_point_2d<unsigned> upoint_2d;
} //namespace cge 

#endif //POINT_2D_H

point_2d.cpp:

#include "point_2d.h"

template<typename T>
constexpr cge::basic_point_2d<T>::basic_point_2d(T _X, T _Y) noexcept:
    x(_X), y(_Y)
{
}

template<typename T>
template<typename U>
constexpr cge::basic_point_2d<T>::basic_point_2d(const basic_point_2d<U>& _Right) noexcept:
    x(static_cast<U>(_Right.x)), y(static_cast<U>(_Right.y))
{
}

template<typename T>
constexpr bool cge::basic_point_2d<T>::equal(const basic_point_2d<T>& _Right) const noexcept
{
    return(this->x == _Right.x && this->y == _Right.y);
}

template<typename T>
constexpr bool operator==(const cge::basic_point_2d<T>& _Left, 
    const cge::basic_point_2d<T>& _Right) noexcept
{
    return(_Left.equal(_Right));
}

template<typename T>
constexpr bool operator!=(const cge::basic_point_2d<T>& _Left, 
    const cge::basic_point_2d<T>& _Right) noexcept
{
    return(!(_Left == _Right));
}

My makefile looks like this:

test: main.o point_2d.o
    g++ main.o point_2d.o -o test

main.o: main.cpp
    g++ -c main.cpp -std=c++1z 

point_2d.o: point_2d.cpp point_2d.h
    g++ -c point_2d.cpp -std=c++1z

And when I compile the program I have these surprises:

In file included from point_2d.cpp:1:
point_2d.h:26:18: error: declaration of template parameter 'T' shadows template
parameter
         template<typename T>
                  ^~~~~~~~
point_2d.h:7:14: note: template parameter 'T' declared here
     template<typename T>
              ^~~~~~~~
point_2d.h:29:18: error: declaration of template parameter 'T' shadows template
parameter
         template<typename T>
                  ^~~~~~~~
point_2d.h:7:14: note: template parameter 'T' declared here
     template<typename T>
              ^~~~~~~~
mingw32-make: *** [makefile:8: point_2d.o] Error 1

I searched a lot on the internet, but could not find any solution that was satisfactory to the problem.

    

asked by

anonymous 11.10.2018 / 14:16

Как сказано в следующем фрагменте кода, это обходной путь для gcc 4.4. ошибка, которую я, вероятно, должен удалить сейчас. Увидеть Параметры шаблонов шаблонов и шаблонов с переменными параметрами с помощью gcc 4.4 для фона к этому.

В любом случае это приводит к ошибке в Debian Wheezy с clang 3.4.2-4, перенесенной из нестабильного состояния. Это прекрасно работает с gcc 4.9, также портированной с нестабильной (и 4.7) на Debian Wheezy.

// Workaround for gcc 4.4 bug. See https://stackoverflow.com/q/8514633/350713
template <typename S, typename T,
template <typename S, typename T, typename... Args> class C,
typename... Args>
struct maptype
{
typedef C<S, T, Args...> type;
};

int main(void){}

Ошибка

clang++ -o shadow.ocl -c -ftemplate-depth-100 -fno-strict-aliasing -fno-common -ansi -Wextra -Wall -Werror -Wno-unused-function -Wc++0x-compat -Wpointer-arith -Wcast-qual -Wcast-align -std=c++11 -mtune=native -msse3 -O3 shadow.cc
shadow.cc:3:23: error: declaration of 'S' shadows template parameter
template <typename S, typename T, typename... Args> class C,
^
shadow.cc:2:20: note: template parameter is declared here
template <typename S, typename T,
^
shadow.cc:3:35: error: declaration of 'T' shadows template parameter
template <typename S, typename T, typename... Args> class C,
^
shadow.cc:2:32: note: template parameter is declared here
template <typename S, typename T,
^
2 errors generated.

Я вижу, по крайней мере, пару внешне похожих вопросов по SO, т.е.
Clang VS VC ++:»ошибка: объявление параметра шаблона теней ‘T’» а также
Шаблон C ++, который работал в старом gcc, приводит к ошибке «Параметр шаблона тени» в clang ++
но для меня не очевидно, являются ли они другой проблемой или той же самой проблемой.

Пояснения приветствуются. Я не пишу на C ++ регулярно, и прошло много времени с тех пор, как я смотрел на параметры шаблона шаблона.

2

Решение

Имена S, T, Args в аргументе шаблона шаблона C

template <typename S, typename T, typename... Args> class C

лишние и имеют те же имена, что и S, T, Args от maptype,
Тот факт, что имена идентичны, приводит к ошибке тени на clang.

Так что вы можете написать

template <typename S,
typename T,
template <typename, typename, typename...> class C,
typename... Args>
struct maptype;

или дать разные имена (для целей документации, поскольку они не могут быть использованы)

template <typename S,
typename T,
template <typename S_Type, typename T_Type, typename... Args_Type> class C,
typename... Args>
struct maptype;

4

Другие решения

  • Forum
  • General C++ Programming
  • declaration of … shadows template parm

declaration of … shadows template parm …

I cannot figure this one out, nor do I understand how to fix it.

My biginteger class is declared thus:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
namespace duthomhas
  {
  ...

  template <typename AllocatorType>
  class biginteger_t
    {
    //------------------------------------------------------------------------
    public: // types
    //------------------------------------------------------------------------

      typedef AllocatorType                 alloc_t;
      typedef typename alloc_t::value_type  value_t;
      typedef std::deque <value_t, alloc_t> array_t;
      typedef typename array_t::size_type   index_t;

      typedef biginteger_t <alloc_t>        biginteger;

    ...

      template <typename CharT, typename TraitsT, typename AllocT>
      std::basic_string <CharT, TraitsT, AllocT>
      basic_string( unsigned radix = 10 ) const
        {
        ...
        }

      std::string  string(  unsigned radix = 10 ) const { return basic_string <char,    std::char_traits <char>    , std::allocator <char>    > ( radix ); }
      std::wstring wstring( unsigned radix = 10 ) const { return basic_string <wchar_t, std::char_traits <wchar_t> , std::allocator <wchar_t> > ( radix ); }

    ...

      template <typename CharT, typename TraitsT, typename AllocT>
      friend
      std::basic_ostream <CharT, TraitsT> &
      operator << (
        std::basic_ostream <CharT, TraitsT> & outs,
        const biginteger_t <AllocT>         & n
        );
    };

  ...
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
  template <typename CharT, typename TraitsT, typename AllocT>
  std::basic_ostream <CharT, TraitsT> &
  operator << (
    std::basic_ostream <CharT, TraitsT> & outs,
    const biginteger_t <AllocT>         & n
    ) {
    std::basic_string <CharT, TraitsT, std::allocator <CharT> >
    s = n.basic_string <CharT, TraitsT, std::allocator <CharT> > ();  // todo: add base conversion based upon stream's fmtflags
    return outs << s;
    }
1
2
  ...
  } // namespace duthomhas 

The compiler complains thusly:

In file included from a.cpp:1:
bignum.hpp: In function 'std::basic_ostream<_CharT, _Traits>& duthomhas::operator<<(std::basic_ostream<_CharT, _Traits>&, const duthomhas::biginteger_t<AllocT>&)':
bignum.hpp:1516: error: expected primary-expression before ',' token
bignum.hpp:1516: error: declaration of 'std::basic_string<CharT, TraitsT, std::allocator<_CharT> > TraitsT'
bignum.hpp:1509: error:  shadows template parm 'class TraitsT'
bignum.hpp:1516: error: invalid declarator before '>' token

I’m not sure exactly where I’m crossing names, but I think it has something to do with allowing the biginteger type to be templated…

I’ve tried changing all the stream/string template names, and also the name of my basic_string function, but I get the exact same errors.

Where exactly am I going wrong?

Thank you for reading.

LOL, I think I solved it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  template <typename AllocatorType>
  class biginteger_t
    {
    ...

      // What'd'ya know? I moved this inside the class block, with a friend status...
      template <typename CharT, typename TraitsT>
      friend
      std::basic_ostream <CharT, TraitsT> &
      operator << (
        std::basic_ostream <CharT, TraitsT> & outs,
        const biginteger                    & n
        ) {
        // todo: add base conversion based upon stream's fmtflags
        return outs << n.basic_string <CharT, TraitsT, std::allocator <CharT> > ();
        }

    };

Naturally, it compiles swimmingly.

I would like to know, if there is one, an answer to the original problem though… What would I have to do to declare my friend insertion operator outside the class’s declaration block?

You’ve got to be kidding me. I didn’t know this «friend defined inside a class» monster. Could you explain what part of the code can see it and use it? Does the code get inlined? What I got from google goes like this: it is defined in the surrounding namespace, but is visible only inside the class.

Anyways, I think what you needed to do in your original code was:

1
2
3
    std::basic_string <CharT, TraitsT, std::allocator <CharT> >
    s = n.template  basic_string <CharT, TraitsT, std::allocator <CharT> > ();  // todo: ...
    return outs << s;

The type of

n

depends on a template parameter and the compiler assumes that basic_string is a member object that is not a template. Therefore the following

<

is interpreted as the less-than operator. Inside the class, the type of

n

is not anymore dependent on the template parameter, in the sense that the declaration of

n

can be located in the current class template. But I am still learning how those rules work exactly. The explanation I had in my head doesn’t cover this case. I just gave you my intuition.

Regards

Last edited on

simeonz wrote:
You’ve got to be kidding me. I didn’t know this «friend defined inside a class» monster. Could you explain what part of the code can see it and use it? Does the code get inlined?

Friend functions can be defined inside template declarations, but it will not get istantiated until
a concrete class of the template is actually created.
here is some info from ‘templates — the complete guide’

However, an interesting effect occurs when a friend function is defined in a class template
because anything that is only declared in a template isn’t a concrete entity until
the template is instantiated. Consider the following example:

1
2
3
4
5
6
template <typename T> 
class Creator { 
    friend void appear() {  // a new function ::appear(), but it doesn't // exist until Creator is instantiated 
    } 
}; 
1
2
Creator<void> miracle;  // ::appear() is created at this point 
Creator<double> oops;   // ERROR: ::appear() is created a second time!  

In this example, two different instantiations create two identical definitions—a direct violation of the ODR (see Appendix A).

We must therefore make sure the template parameters of the class template
appear in the type of any friend function defined in that template
(unless we want to prevent more than one instantiation of a class template
in a particular file, but this is rather unlikely).
Let’s apply this to a variation of our previous example:

1
2
3
4
5
6
template <typename T> 
class Creator { 
    friend void feed(Creator<T>*){  // every T generates a different // function ::feed() 
    } 
}; 
1
2
Creator<void> one;     // generates ::feed(Creator<void>*) 
Creator<double> two;   // generates ::feed(Creator<double>*)  

In this example, every instantiation of Creator generates a different function.
Note that even though these functions are generated as part of the instantiation of a template,
the functions themselves are ordinary functions, not instances of a template.

Also note that because the body of these functions is defined inside a class
definition, they are implicitly inline.
Hence, it is not an error for the same function to be generated in two different translation units.

Woah, that is awesomely cool! I didn’t know about the template qualifier and how it worked like that!

The insertion operator really does not need to be a friend of the class, so I am now using your excellent solution:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
...

namespace duthomhas
  {

  ...

  template <typename AllocatorType>
  class biginteger_t
    {
    ...
    };

  ...

  template <typename AllocT, typename CharT, typename TraitsT>
  std::basic_ostream <CharT, TraitsT> &
  operator << (
    std::basic_ostream <CharT, TraitsT> & outs,
    const biginteger_t <AllocT>         & n
    ) {
    return outs << n.template basic_string <CharT, TraitsT, std::allocator <CharT> > ();  // todo: ...
    }

  } // namespace duthomhas

...

It is legal to define a friend function that way so long as certain conditions are met (mainly, that the class is non-local).

Thank you!

Well guys, I am always happy to learn new aspects. On the other hand, C++ classes are such mix of interface and implementation. Thanks for the info.

Last edited on

Topic archived. No new replies allowed.

I’m trying to do a graphite program, but I’m having a problem…
My code and this:

Main. cpp:

#include "point_2d.h"
#include <iostream>

int main()
{
cge::point_2d p(5, 5);
p.x = 6;
std::cout << p.x << " " << p.y << std::endl;
std::cin.get();
return 0;
}

point_2d.h:

#ifndef POINT_2D_H
#define POINT_2D_H

namespace cge
{

template&lt;typename T&gt;
struct basic_point_2d
{

    typedef T value_type;

    constexpr basic_point_2d() noexcept = default;

    constexpr basic_point_2d(const basic_point_2d&amp;) noexcept = default;

    constexpr basic_point_2d&amp; operator=(const basic_point_2d&amp;) noexcept = default;

    template&lt;typename U&gt;
    constexpr explicit basic_point_2d(const basic_point_2d&lt;U&gt;&amp;) noexcept; //Conversions

    constexpr basic_point_2d(T, T) noexcept; //Constructors

    constexpr bool equal(const basic_point_2d&amp;) const noexcept;

    template&lt;typename T&gt;
    friend constexpr bool operator==(const basic_point_2d&lt;T&gt;&amp;, const basic_point_2d&lt;T&gt;&amp;) noexcept; 

    template&lt;typename T&gt;
    friend constexpr bool operator!=(const basic_point_2d&lt;T&gt;&amp;, const basic_point_2d&lt;T&gt;&amp;) noexcept;


    T x = T();
    T y = T();

}; //struct basic_point_2d

typedef basic_point_2d&lt;int&gt; point_2d;
typedef basic_point_2d&lt;unsigned&gt; upoint_2d;

} //namespace cge

#endif //POINT_2D_H

point_2d.cpp:

#include "point_2d.h"

template<typename T>
constexpr cge::basic_point_2d<T>::basic_point_2d(T _X, T _Y) noexcept:
x(_X), y(_Y)
{
}

template<typename T>
template<typename U>
constexpr cge::basic_point_2d<T>::basic_point_2d(const basic_point_2d<U>& _Right) noexcept:
x(static_cast<U>(_Right.x)), y(static_cast<U>(_Right.y))
{
}

template<typename T>
constexpr bool cge::basic_point_2d<T>::equal(const basic_point_2d<T>& _Right) const noexcept
{
return(this->x == _Right.x && this->y == _Right.y);
}

template<typename T>
constexpr bool operator==(const cge::basic_point_2d<T>& _Left,
const cge::basic_point_2d<T>& _Right) noexcept
{
return(_Left.equal(_Right));
}

template<typename T>
constexpr bool operator!=(const cge::basic_point_2d<T>& _Left,
const cge::basic_point_2d<T>& _Right) noexcept
{
return(!(_Left == _Right));
}

My makefile and so:

test: main.o point_2d.o
g++ main.o point_2d.o -o test

main.o: main.cpp
g++ -c main.cpp -std=c++1z

point_2d.o: point_2d.cpp point_2d.h
g++ -c point_2d.cpp -std=c++1z

and when I compel the program I have these surprises:

In file included from point_2d.cpp:1:
point_2d.h:26:18: error: declaration of template parameter 'T' shadows template
parameter
template<typename T>
^~~~~~~~
point_2d.h:7:14: note: template parameter 'T' declared here
template<typename T>
^~~~~~~~
point_2d.h:29:18: error: declaration of template parameter 'T' shadows template
parameter
template<typename T>
^~~~~~~~
point_2d.h:7:14: note: template parameter 'T' declared here
template<typename T>
^~~~~~~~
mingw32-make: *** [makefile:8: point_2d.o] Error 1

I looked a lot on the internet, but I couldn’t find any satisfactory solution to the problem.

Проблема с шаблонами. Не понимаю в чем проблема, вроде пол-года назад писал тоже самое и все работало, а сейчас компилятор жалуется (на template… перед class Node…) Visual S вообще не запускает, а online компилятор указывает на эту строку, а именно :

declaration of template parameter ‘T’ shadows template parameter

Не понимаю, что не так, объясните.

    template<typename T>
class List {
public:

    List();
    void push_back(T data);
private:

    template<typename T>
    class Node {
    private:
        T data;
        Node* pNext;
    public:
        Node(T data = T(), Node* pNext = nullptr) {
            this->pNext = pNext;
            this->data = data;
        }
    };
    Node<T>* head;
    int Size = 0;
};





template<typename T>
List<T>::List() {
    head = nullptr;
    Size = 0;
}

template<typename T>
void List<T>::push_back(T data) {
    if (head == nullptr) {
        head = new Node<T>(T data);
    }
    else {
        Node* current = this->head;
        while (current->pNext != nullptr) {
            current = current->pNext;
        }
        current->pNext = new Node<T>(data);
    }
    Size++;
}

int main()
{
    List<int> Data;
} 
    
     

Понравилась статья? Поделить с друзьями:
  • Error debugger is found on this machine
  • Error debug is not a valid attribute for a play
  • Error deadly premonition
  • Error deadlock detected sqlstate 40p01
  • Error dds reader tried to allocate