Error need typename before because is a dependent scope

I want to create a template as follows. I want to delete a list of items from vector vec1. And the indexes of the items I want to delete are stored in index_list. #include using

I want to create a template as follows. I want to delete a list of items from vector vec1. And the indexes of the items I want to delete are stored in index_list.

#include <vector>

using namespace std;

template <typename a_type>
bool vector_remove(vector< a_type > & vec1, vector< int > index_list)
{
    //index_list is sorted in order from small to large.

    if(index_list.size() > vec1.size())
    {
        cout << "ERROR in 'vector_remove()': index_list is longer than vec1."<<endl;
        return false;
    }
    if(index_list.size() == vec1.size())
    {
        vec1.clear();
        return true;
    }
    vector< int >::iterator ind_pt = index_list.begin();
    vector< a_type >::iterator vec1_pre = vec1.begin();
    vector< a_type >::iterator vec1_pos = vec1.begin();
    int vec1_ind = 0;
    while(ind_pt != index_list.end() && vec1_pos != vec1.end())
    {
        if(*ind_pt == vec1_ind)
        {
            ind_pt ++;
            vec1_pos ++;
            vec1_ind ++;
        }
        else if( *ind_pt > vec1_ind )
        {
            *(vec1_pre) = *(vec1_pos);
            vec1_pos ++;
            vec1_pre ++;
            vec1_ind ++;
        }
        else
        {
            cout << "ERROR in 'vector_remove'." <<endl;
            return false;
        }
    }
    while(vec1_pos != vec1.end())
    {
        *(vec1_pre) = *(vec1_pos);
        vec1_pos ++;
        vec1_pre ++;
    }
    // the above codes are to put all the rejected elements to the end of the vec1.

    // pop back all the rejected elements.
    while(vec1_pre != vec1.end() )
    {
        vec1.pop_back();
    }

    return true;
}

But it returns a lot of errors:

In file included from demo.cpp:3:0:
my_vector.h: In function ‘bool vector_remove(std::vector<a_type>&, std::vector<int>)’:
my_vector.h:21:2: error: need ‘typename’ before ‘std::vector<a_type>::iterator’ because ‘std::vector<a_type>’ is a dependent scope
  vector< a_type >::iterator vec1_pre = vec1.begin();
  ^
my_vector.h:21:29: error: expected ‘;’ before ‘vec1_pre’
  vector< a_type >::iterator vec1_pre = vec1.begin();
                             ^
my_vector.h:22:2: error: need ‘typename’ before ‘std::vector<a_type>::iterator’ because ‘std::vector<a_type>’ is a dependent scope
  vector< a_type >::iterator vec1_pos = vec1.begin();
  ^
my_vector.h:22:29: error: expected ‘;’ before ‘vec1_pos’
  vector< a_type >::iterator vec1_pos = vec1.begin();
                             ^
my_vector.h:24:38: error: ‘vec1_pos’ was not declared in this scope
  while(ind_pt != index_list.end() && vec1_pos != vec1.end())
                                      ^
my_vector.h:34:6: error: ‘vec1_pre’ was not declared in this scope
    *(vec1_pre) = *(vec1_pos);
      ^
my_vector.h:45:8: error: ‘vec1_pos’ was not declared in this scope
  while(vec1_pos != vec1.end())
        ^
my_vector.h:47:5: error: ‘vec1_pre’ was not declared in this scope
   *(vec1_pre) = *(vec1_pos);
     ^
my_vector.h:54:8: error: ‘vec1_pre’ was not declared in this scope
  while(vec1_pre != vec1.end() )

could anyone help me solve this?

  • Forum
  • Beginners
  • Erro: Need typename because vector<type>

Erro: Need typename because vector<type> is a dependent scope

I am writing a class for a priority vector, but I am facing trouble when I declare an iterator with <type> which is the typename of my class template. The error is in line 37.

error: need ‘typename’ before ‘std::vector<type>::iterator’ because ‘std::vector<type>’ is a dependent scope|

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
  #include<iostream>
#include<vector>
#include<typeinfo>

using namespace std;

string first (string a, string b){
int siz = min(a.size(), b.size());
int place = 0;
while (a[place]==b[place] && place<siz){
    place++;
}
if (a[place]>b[place]){
    return b;
}
else if (a[place]<b[place]){
    return a;
}
}

template <class type>
class priority_vector{
public:
type check;
string check2;
vector <type> pv;
bool isString(){
if (typeid(type).name()==typeid(check2).name()){return true;}
else {return false;}
}
void push_in(type input){
if (isString()){
    if (pv.size()==0){
        pv.push_back(input);
    }
    else{
        vector <type> :: iterator vit;
        vit = pv.begin();
        while (first(*pv, input)==*pv){
            pv ++;
        }
        vit.insert(vit, input);
    }
}
else{
    if(pv.size()==0){
        pv.push_back(input);
    }
    else{
        vector <type> :: iterator vit;
        vit = pv.begin();
        while (*pv<input){
            pv++;
        }
        vit.insert(vit, input);
    }
}
}
type operator[](int a){
return pv[a];
}
};

int main(){
priority_vector <string> v_s;
int n;
cin>>n;
int in;
for (int i=0; i<n; i++){
    cin>>n;
    v_s.push_in(n);
}
for (int i=0; i<n; i++){
    cout<<v_s[i];
}
return 0;
}

The error is pretty clear. You need to use typename to tell the compiler that vector<type>::iterator is a type, otherwise the compiler will assume it’s a variable or function.

 
typename vector<type>::iterator vit;

Last edited on

Yeah, but why does it need that? Type was already declared at the template.

Topic archived. No new replies allowed.

Содержание

  1. Error need typename before
  2. When and why the template & typename keywords are needed
  3. Template Keyword
  4. Typename Keyword
  5. who am i
  6. what is this
  7. Error need typename before
  8. Error need typename before
  9. Error need typename before

Error need typename before

тебе же русским языком говорят

I invented the term Object-Oriented, and I can tell you I did not have C++ in mind. (c)Alan Kay

My other car is cdr.

Q: Whats the object-oriented way to become wealthy?
A: Inheritance

Ага) Думал, что под ‘typename’ подразумевается ‘Summable’. В голову не пришло, что ‘typename’ надо написать

В книжке «Programming — C++ — C++ by dissection — Standard template library (STL) A tutorial.pdf» написано без ‘typename’. Ошибочка, видимо

Тааа это обычная компилятор-раздолбайство.

Гцц обычно всегда все надо. Он у нас типа строгий. Усе типа как положено!
В студии не то, что бы на стандарт наложено. просто она умная, и очень хорошо понимает желания программиста.

Не требует лишних глупых телодвижений.

В книжке «Programming — C++ — C++ by dissection — Standard template library (STL) A tutorial.pdf» написано без ‘typename’. Ошибочка, видимо

Сие по теме. Не веришь — компиль пример из книги в студии.
Отрокам на ус — есть стандарт, и есть студия. Дабы не растерялись из-за километровых ошибок, что сопутствуют шаблончикам, как мухи навозу.

К тому же я не люблю студию. из-за слишком уж тупой сборки.
Не осилил покамест условную сборку под виндой. От того и маюсь нынче.

Как сделать: если некоторый дефайн (или какая то херь в ключе компиля)
вкл — включить в сборку такие то файлы cpp.

Источник

When and why the template & typename keywords are needed

When working with C++ templates you’ll likely be familiar with the template and typename keywords in the context of template declarations, for example:

However, there are two other contexts where it is necessary to use the template and typename keywords, which often cause confusion at first sight. This post aims to demystify these cases, explaining when and why they are needed.

Template Keyword

Consider the following code example:

At first glance this code looks correct, however, when you compile this you will get an error that looks something like:

error: expected primary-expression before ‘float’

Being faced with this error message it may not be clear what the problem is. The reason for the error can actually be found in two-phase name lookup; the rule that every template is compiled in two phases, firstly for general syntax and again once any dependent names (names that depend on a template parameter) are known. More specifically, due to a grammar ambiguity in C++; being that the token in an expresion such as f.bar () can be parsed either as the start of a template argument list of a call to a member function template specialisation or as a less than operator, the compiler is not able to differentiate until the type of f is known.

This means that in a case such as this when f is a dependent type; foo , the compiler does not yet know what type f is, so the . operator is unable to lookup bar and the compiler treats it purely syntactically as a field of foo so the following is therefore interpreted as a less than operator. In order to instruct the compiler that this is, in fact, a call to a member function template specialisation it is necessary to add the template keyword immediately after the . operator:

This same rule is also applied to the pointer operator and to nested name qualifiers:

An interesting case for this is where you have to use the template keyword even when it involves the this pointer:

This might seem odd, but there are cases due to inheritance where the full type of the this pointer cannot be known until the class template is specialised, such as when the type has a dependant base class.

For those interested in the C++ standardese, the section which describes this rule is as follows:

$14.2/4: When the name of a member template specialization appears after . or -> in a postfix-expression, or after nested-name-specifier in a qualified-id, and the postfix-expression or qualified-id explicitly depends on a template-parameter (14.6.2), the member template name must be prefixed by the keyword template. Otherwise the name is assumed to name a non-template.

Typename Keyword

Take another code example:

If you were to compile this code as it is, you would get an error for the line using t = type_or_value ::tv; something like:

error: need ‘typename’ before ‘type_or_value ::tv’ because ‘type_or_value ‘ is a dependent scope

This error is better than the previous one as it tells you what to do, essentially add the typename keyword immediately before the expression. But why is this necessary? Again the reason for this can be found in the two-phase name lookup.

When the compiler parses code like this involving a dependant type, in this case, type_or_value it cannot know whether the member tv resolves to a type or a non-type and assumes the latter. In order to instruct the compiler that tv is, in fact, resolves to a type it is necessary to add the typename keyword immediately before the expression:

However now that this keyword is there the compiler assumes that the expression will always resolve to a type, so if a later instantiation were to not conform to this, the compiler would through an error. For example:

This would result in an error like:

error: no type named ‘tv’ in ‘struct type_or_value ‘

The typename keyword is not only needed in this case, it’s needed anywhere an unknown member exists in a context where either a type or a non-type is valid. For example:

who am i

I am a software developer at Codeplay Software, where I work on SYCL; an open standard C++ programming model for heterogeneous systems. I am an active contributor to the SYCL and the C++ standards. I am a C++ and game dev enthusiast.

what is this

This is a programming blog about C++, gamedev, and heterogeneous computing.

Источник

Error need typename before

I’m trying to make a silly function to show the content of maps as follows:

However, I got this error in the ‘for’ line: «error: expected ‘;’ before ‘it’» (and then errors that it is not declared, etc). I’m sure that there is no missing ; in other functions. If you try to write a random line before that you get no error there for example, always in the for.

It is there something that you need to do with iterators when you declare generic datatypes?

Apart from that

gcc wrote:
In function ‘void show_map(const std::map&)’:
error: need ‘typename’ before ‘std::map::iterator’ because ‘std::map’ is a dependent scope
clang wrote:
error: missing ‘typename’ prior to dependent type name ‘std::map::iterator’

So it should be for ( typename std::map::const_iterator it = src.begin();

or, avoid the mess with:

for ( auto it = src.begin(); .

Or maybe go with the range-based for loop:

auto is definitely a friend to you wherever templates are involved.

Источник

Error need typename before

Okay, so here is my updated header file

And here is my updated .cpp file

Your suggestions have cut down my number of errors, so thank you. But Im still getting this one error for line 7 in my .cpp file

error: need ‘typename’ before ‘Ntree ::node’ because ‘Ntree ‘ is a dependent scope.

Apparently there is something wrong with my return type. Any help on this?

So I literally had to write the word ‘typename’ before my return type on line 7. That fixed the issue (but now I am dealing with other errors). Can anyone explain why this works? I’ve never had to do this before.

> error: need ‘typename’ before ‘Ntree ::node’ because ‘Ntree ‘ is a dependent scope.

You may want to read: ‘Why can’t I separate the definition of my templates class from its declaration and put it inside a .cpp file?’ in https://isocpp.org/wiki/faq/templates

So I have to move all my function definitions into my header file? And remove my .cpp file altogether?

Need help serializing this N-ary tree into a file.

The function call in main looks like this: tree.serialize( «foodtree.out» );

I stored the N children of the tree in a vector called ‘children’. Even though I declared ‘children’ publicly in a struct within the class, my compiler says it is not within scope when I try to use it in my serialize and serializeRec function. Any idea why this is happening?

Here is my .h file:

I have made some progress but still have a few bugs to fix. I am still trying to make my serialize function, so please focus on that.

Here is my main (given by professor)

Here is my .h file (made by me):
Take a look at some comments I put in here.

My serialize function works, in that it prints out what is expected, however, I get a «program.exe. has stopped working» message pop up. So It seems my program crashed after printing the tree.

Here is my output:

Any idea why my program crashes even though the function seems to work?

In your main, at the very end, I see that you commented out the call to deserialize(), but you did not comment out assert() function, which if you take a look is actually an #include .h file. I am guessing your professor will use that file to check your work? The program seems to work fine if you comment it out for testing.

I would suggest adding in your deserialize funtion, then leave assert() commented out and test to see what happens.

I figured that was it so I made my deserialize function. I’ve also made my toString function.

However, my assert still seems to fail, and my toString is not working at all:

I’ve commented out my assertion in main(we’ll deal with that later). Right now, my call toString() is giving me an error in main, saying no match for ‘operator Last edited on

Источник

Error need typename before

The problem is that I’m giving a value to a cv-qualifier, so I either have to make a copy of it, or pass it by value. But I’m not allowed to change anything in the code, so I’m kinda having some real trouble with the situation. Could anyone help me out? I’ve been at this for weeks. I didn’t post the whole code to keep it easy to read, but if you need it, let me know and I’ll post it up. But here is the snippet with the source of the error:

Line 4: anEntry is described as const. Therefore you can’t assign anything to it.

Line 4: You’re subscripting out of bounds. if items has 10 entries, those items are 0-9.

Line 5: You have no guarantee that size() items are allocated. If you’re trying to add an item here, you need to do items.push_back(temp)

Line 6: What’s the point of popping the item you just added?

Is the purpose of remove to remove a specific entry (anEntry)? If so, don’t you need to search the vector for the matching entry?

This function is not designed to add anything to the vector. Its supposed to swap the last item in items , which items.size() points to, with anEntry , and once anEntry becomes the final entry in the vector, items.pop_back() removes it.

> Line 4: anEntry is described as const. Therefore you can’t assign anything to it.

Right. So how would I go about dealing with that?

> Line 4: You’re subscripting out of bounds. if items has 10 entries, those items are 0-9.

I’m confused. Are you saying that items.size() is items 0 — 9 ?

> Is the purpose of remove to remove a specific entry (anEntry)? If so, don’t you need to search the vector for the matching entry?

You’re right about, I’ll go ahead and fix up the code. Meantime, how would I pass by value here or make a copy of the cv-qualifier variable?

the last item in items, which items.size() points to

No. items[items.size()] is out of bounds.
As I said before, if size is 10, then the valid entries are 0 — 9. items[10] is not valid.

I’m not understanding why you’re trying to swap something into anEntry. If you can’t change the function declaration, then it would seem that was not the intent.

Are you saying that items.size() is items 0 — 9 ?

Yes. Arrays and vectors in C++ are numbered from 0. Therefore, valid entries are 0 — 9.

how would I pass by value here

I thought you said you can’t change the declaration, which is what you would have to do to pass by value. In any case, I’m not sure that’s what you want to do.

or make a copy of the cv-qualifier variable?

temp is in fact a copy of anEntry, but I’m guessing that you don’t need that.

Its supposed to swap the last item in items, which items.size() points to, with anEntry, and once anEntry becomes the final entry in the vector, items.pop_back() removes it.

I’m sorry, but that makes no sense to me given that anEntry is const. What is the point of making anEntry the final entry in the vector, only to pop it?

It makes a lot more sense to me that your remove function would search the vector to find an entry that matches anEntry. A simple for loop would work for this assuming ItemType has an equality operator. If a matching entry is not found, return false. If a matching entry is found, there use items.erase() to get rid of the entry you found.

oh, I get what you’re saying about the items.size() business now, thanks for clearing all that up. I can’t believe I missed something so obvious.

anyways, here’s what I got when I changed it up to find the index of anEntry and erase it:

and the error message now:

I don’t understand why it’s saying that, when I did at the top.

Don’t you just love error messages involving templates? 🙂

What that cryptic message message is trying to tell you is that std::vector does not have an erase function that takes an item by value, which is what you specified at line 5. erase requires an iterator, not a value type.

There is also a problem with your while loop. What happens if anEntry is not in the vector? You have no condition to exit out of the loop when you reach the end of the vector. This was why I suggested a for loop.

Consider the following:

I tried putting that into my code, and what do you know. more error messages lol. I tried changing it up to make it work, but my attempts didn’t work either so I just reverted it back to what you wrote. Here’s what I got:

Since you didn’t post vectorbag.h, I was uncertain of the type of items, nor could I compile the code I posted to check for errors.

Line 6 should be an iterator of whatever type items is.
Assuming items is: vector items; then line 6 should be:

If items is some type other than vector then you need to adjust the iterator accordingly.

Sorry for the confusion.

I’m still getting errors, I don’t know why.

Источник

When working with C++ templates you’ll likely be familiar with the template and typename keywords in the context of template declarations, for example:

template <typename T>
void foo(T t);

However, there are two other contexts where it is necessary to use the template and typename keywords, which often cause confusion at first sight. This post aims to demystify these cases, explaining when and why they are needed.

Template Keyword

Consider the following code example:

template <typename T>
struct foo {
  template <typename U>
  void bar() { }
};

template <typename T>
void func(foo<T> f) {
  f.bar<float>();
}

At first glance this code looks correct, however, when you compile this you will get an error that looks something like:

error: expected primary-expression before ‘float’

Being faced with this error message it may not be clear what the problem is. The reason for the error can actually be found in two-phase name lookup; the rule that every template is compiled in two phases, firstly for general syntax and again once any dependent names (names that depend on a template parameter) are known. More specifically, due to a grammar ambiguity in C++; being that the < token in an expresion such as f.bar<float>() can be parsed either as the start of a template argument list of a call to a member function template specialisation or as a less than operator, the compiler is not able to differentiate until the type of f is known.

This means that in a case such as this when f is a dependent type; foo<T>, the compiler does not yet know what type f is, so the . operator is unable to lookup bar and the compiler treats it purely syntactically as a field of foo<T> so the following < is therefore interpreted as a less than operator. In order to instruct the compiler that this is, in fact, a call to a member function template specialisation it is necessary to add the template keyword immediately after the . operator:

template <typename T>
struct foo {
  template <typename U>
  void bar() { }
};

template <typename T>
void func(foo<T> f) {
  f.template bar<float>();
}

This same rule is also applied to the pointer operator and to nested name qualifiers:

template <typename T>
struct foo {
  template <typename U>
  void bar() { }
};

template <typename T>
void func(foo<T> *fp) {
  fp->template bar<float>();
}
template <typename T>
struct foo {
  template <typename U>
  static void bar() { }
};

template <typename T>
void func() {
  foo<T>::template bar<float>();
}

An interesting case for this is where you have to use the template keyword even when it involves the this pointer:

template <typename T>
struct foo_base {
  template <typename U>
  void base_bar() {
  }
};

template <typename T>
struct foo : public foo_base<T> {
  template <typename U>
  void bar() {
    this->template base_bar<U>();
  }
};

This might seem odd, but there are cases due to inheritance where the full type of the this pointer cannot be known until the class template is specialised, such as when the type has a dependant base class.

For those interested in the C++ standardese, the section which describes this rule is as follows:

$14.2/4:
When the name of a member template specialization appears after . or -> in a postfix-expression, or after nested-name-specifier in a qualified-id, and the postfix-expression or qualified-id explicitly depends on a template-parameter (14.6.2), the member template name must be prefixed by the keyword template. Otherwise the name is assumed to name a non-template.

Typename Keyword

Take another code example:

template <typename T>
struct type_or_value;

template <>
struct type_or_value<int> {
  static const bool tv = true;
};

template <>
struct type_or_value<float> {
  using tv = float;
};

template <typename T>
void func() {
  using t = type_or_value<T>::tv;
  bool v = type_or_value<T>::tv;
}

If you were to compile this code as it is, you would get an error for the line using t = type_or_value<T>::tv; something like:

error: need ‘typename’ before ‘type_or_value::tv’ because ‘type_or_value’ is a dependent scope

This error is better than the previous one as it tells you what to do, essentially add the typename keyword immediately before the expression. But why is this necessary? Again the reason for this can be found in the two-phase name lookup.

When the compiler parses code like this involving a dependant type, in this case, type_or_value<T> it cannot know whether the member tv resolves to a type or a non-type and assumes the latter. In order to instruct the compiler that tv is, in fact, resolves to a type it is necessary to add the typename keyword immediately before the expression:

template <typename T>
struct type_or_value;

template <>
struct type_or_value<int> {
  static const bool tv = true;
};

template <>
struct type_or_value<float> {
  using tv = float;
};

template <typename T>
void func() {
  using t = typename type_or_value<T>::tv;
  bool v = type_or_value<T>::tv;
}

However now that this keyword is there the compiler assumes that the expression will always resolve to a type, so if a later instantiation were to not conform to this, the compiler would through an error. For example:

int main () {
  func<int>(f);
}

This would result in an error like:

error: no type named ‘tv’ in ‘struct type_or_value’

The typename keyword is not only needed in this case, it’s needed anywhere an unknown member exists in a context where either a type or a non-type is valid. For example:

template <typename T>
struct type_or_value;

template <>
struct type_or_value<int> {
  static const bool tv = true;
};

template <>
struct type_or_value<float> {
  using tv = float;
};

template <typename T>
struct foo {
};

template <typename T>
void func() {
  foo<typename type_or_value<T>::tv> f;
}

septe-mber

1 / 1 / 1

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

Сообщений: 123

1

11.05.2013, 19:58. Показов 2527. Ответов 3

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


привет всем! почему выскакивает ошибка /home/september/console/tabld_node/dictionary.cpp:93: ошибка: need ‘typename’ before ‘Dictionary<Key, Value>::Node_key’ because ‘Dictionary<Key, Value>’ is a dependent scope …что не так делаю ? объясните пожалуйста
вот кусок кода

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
template<typename Key, typename Value>
Dictionary<Key, Value>::Node_key* Dictionary<Key, Value>::find_key(Key key)
{
    int i(0);
    if(pm_head_key == NULL)
        return NULL;
    Node_key* tmp = pm_head_key;
    for(; tmp != NULL; tmp = tmp->next)
    {
        if(tmp->key == key)
        {
            m_index_key = i;
            break;
        }
        i++;
    }
    return tmp;
}

пользуюсь qt creater

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



0



ForEveR

В астрале

Эксперт С++

8048 / 4805 / 655

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

Сообщений: 10,562

11.05.2013, 20:05

2

septe-mber,

need ‘typename’ before ‘Dictionary<Key, Value>::Node_key’

Я просто офигеваю честно говоря. Это трудно в гугл забить? Тут блин ведь даже гугл не нужен…
Должно быть

C++
1
2
template<typename Key, typename Value>
typename Dictionary<Key, Value>::Node_key* Dictionary<Key, Value>::find_key(Key key)



1



1804 / 1268 / 935

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

Сообщений: 2,063

11.05.2013, 20:07

3

septe-mber, написано же:

Цитата
Сообщение от septe-mber
Посмотреть сообщение

need ‘typename’ before ‘Dictionary<Key, Value>::Node_key’ because ‘Dictionary<Key, Value>’ is a dependent scope

Нужно поставить typename перед Dictionary<Key, Value>::Node_key



1



1 / 1 / 1

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

Сообщений: 123

11.05.2013, 20:09

 [ТС]

4

ForEveR, затупил конкретно…пока перекур делать…



0



Anyone dealing with templates will eventually run into something like this

// templated class with a type alias for "type"
template <typename T>
struct Obj {
    using type = int;
};

template <typename T>
void f() {
    Obj<T>::type var; // should be "int var;"
}

But wait, there’s an error on the only statement in f()

# clang-3.6
error: expected ';' after expression
    Obj<T>::type var;
       ^
       ;

# gcc-5.1
error: need ‘typename’ before ‘Obj<T>::type’ because ‘Obj<T>’ is a dependent scope
     Obj<T>::type var; // should be "int var;"

gcc’s error is great in this case, telling us we need to add a leading typename to make it:

typename Obj<T>::type var;

The leading typename tells the compiler that Obj<T>::type is a type. But why do we need this? We know that Obj<T> is a dependent type because it depends on T.

First, you have to realize that without a leading typename, the compiler assumes (in the case of a dependent type) that it’s a static member variable, meaning the following is parsed correctly

template <typename T>
struct Obj2 {
    static constexpr int type = 5;
};

template <typename T>
void f2() {
    int n = Obj2<T>::type * 3;
}

So what? Why can’t the compiler just look inside of Obj and see that it has a type member. Well, in the case of template specializations, it can’t. Consider this:

// general case has "using type = int"
template <typename T>
struct Obj {
    using type = int;
};

// specialization for int has "int type = 2"
template <>
struct Obj<int> {
    static constexpr int type = 2;
};

Inside of f() we don’t know which one of these we’re dealing with. f() means it’s using the general template, but f() uses the specialization. The programmer must clarify that they expect a type.

You might be thinking “right, but in this case it’s clear that the body of f() is declaring a variable.” Right you are, but it’s not always this clear. What if instead we had

int x = 5; // global variable x
template <typename T>
void f() {
    Obj<T>::type * x;
}

Now we have two possible versions of this

int * x; // declaring a local variable x of type int*
2 * x; // multiplication expression

Both of these lines make sense, but they mean very different things. It’s not always clear which way it should be parsed.

You’re less likely to see this problem, but I think it’s cool and has the same idea behind it. When your dependent name has a templated member function, the compiler gets confused about what you mean again:

struct Obj {
    template <typename U>
    void m();
};

Now let’s create a variable with dependent type Obj<T> and call m()

template <typename T>
void f() {
    Obj<T> v;
    v.m<int>();
}

But hold on errors! this time clang being more helpful

# gcc-5.1
error: expected primary-expression before ‘int’
     v.m<int>();

# clang-3.6
error: use 'template' keyword to treat 'm' as a dependent template name
    v.m<int>();
      ^
      template 

Huh? template keyword? What’s happening is the compiler doesn’t know that m is a templated member function, we need tell it

v.template m<int>();

Alright so what’s the alternative here. Well, it’s a pretty well known issue with the C++ grammar that without context, you don’t know what certain lines mean. Borrowed from the D docs, consider the line:

A<B,C>D;

This could mean two things, (1) A is a templated class, B and C are template arguments, and D is a variable declared with that type. for example:

template <typename T, typename U> struct A;
using A = int;
using B = int;

A<B,C> D; // A<int,int> D

Or (2), A, B, C, and D are all variables and this is two comparisons separated by a comma

int A{}, B{}, C{}, D{};
(A < B), (C > D);

So, by default the compiler is assuming that m is not a template, which means that it assumes the angle brackets are less than and greater than operators, so it’s parsed as

((v.m) < int) > ();

This could make sense in a different context

template <typename T>
struct Obj {
    int m;
};

And then the following:

int a{};
v.m<a>0;
((v.m < a) > 0

So the “dot template” is needed to say that what follows is a template. Like I said this is far less common, and the syntax is so awkward that it can drive design decisions. If you’ve ever wondered why std::get is a free function, a big part is that std::tuple is often used as a dependent type.

template <typename... Ts>
void f(std::tuple<Ts...>& t) {
    std::get<0>(t); // nice
    t.template get<0>(); // gross
}

Когда я пытаюсь скомпилировать, я получаю следующие ошибки:

 In member function 'double search::IDAstar<State, MoveContainer>::dfs(const State&, double)': 153:18: error: need 'typename' before
'MoveContainer:: const_iterator' because 'MoveContainer' is a dependent scope 153:48: error: expected ';' before 'it' 154:17: error: 'it'
was not declared in this scope
In member function '{anonymous}::State& {anonymous}::State::operator=(const {anonymous}::State&)':
234:9: warning: no return statement in function returning non-void [-Wreturn-type] In instantiation of
'double search::IDAstar<State, MoveContainer>::dfs(const State&, double) [with State = {anonymous}::State; MoveContainer = std::list<search::Move<{anonymous}::State> >]':
122:34: required from 'std::list<State> search::IDAstar<State, MoveContainer>::solve(const State&)
[with State = {anonymous}::State; MoveContainer = std::list<search::Move<{anonymous}::State> >]' 371:55: required from here
152:57: error: invalid initialization of non-const reference of type 'std::list<search::Move<{anonymous}::State> >&' from an rvalue of type
'{anonymous}::State::MoveContainer {aka std::list<search::Move<{anonymous}::State> >}' 153:66: error: dependent-name 'MoveContainer:: const_iterator'
is parsed as a non-type, but instantiation yields a type 153:66: note: say 'typename MoveContainer:: const_iterator' if a type is meant

search_IDAstar.h

///////////////////////////////////////////////////////////////////////////////
//
// search_IDAstar.h
//
///////////////////////////////////////////////////////////////////////////////

#ifndef SEARCH_IDASTAR_H
#define SEARCH_IDASTAR_H

#include <list>
#include <limits> // infinity

namespace search
{
// A Move is a generic successor of a State (see IDAstar below).
template<typename State>
class Move
{
public:

// Create a move to the given successor state with the given cost.
Move(const State& s, double g) :
s(s),
g(g)
{
// empty
}

// Destructor
~Move()
{
// empty
}

// Copy constructor
Move(const Move& copy) :
s(copy.s),
g(copy.g)
{
// empty
}

// Assignment operator
Move& operator= (const Move& rhs)
{
s = rhs.s;
g = rhs.g;
}

// Return successor state.
State state() const
{
return s;
}

// Return cost of this move.
double cost() const
{
return g;
}

private:
State s;
double g;
};

// IDAstar is a generic implementation of the IDA* search algorithm.
//
// Instances of the parameter State should implement the following methods:
//
// double State::h() const;
// bool State::isGoal() const;
// MoveContainer State::successors(std::list<State>& solution) const;
//
// where h() is an admissible heuristic, isGoal() returns true iff the
// state is a goal state, and successors() returns a container of moves,
// each of which implements the following methods:
//
// State state() const;
// double cost() const;
//
// where state() is a successor state and cost() is the cost of the
// corresponding move.  The successors() method may exclude cycles using
// the given partial solution sequence of states.
template<typename State, typename MoveContainer = std::list<Move<State> > >
class IDAstar
{
public:

// Constructor
IDAstar() :
solution(),
solved(false),
fLimit(0),
inf(std::numeric_limits<double>::infinity())
{
// empty
}

// Destructor
~IDAstar()
{
// empty
}

// Use IDA* search to find an optimal path from the given state to a
// goal state.  Return a list of states from the given state to the
// goal state, or an empty list if no solution exists.
std::list<State> solve(const State& s)
{
solution.clear();
solved = false;
fLimit = s.h();
while (!solved && fLimit < inf)
{
fLimit = dfs(s, 0);
}
return solution;
}

private:

// Private unimplemented copy constructor and assignment operator
IDAstar(const IDAstar& copy);
IDAstar& operator= (const IDAstar& rhs);

std::list<State> solution;
bool solved;
double fLimit;
double inf;

double dfs(const State& s, double g)
{
double f = g + s.h();
if (f > fLimit)
{
return f;
}
solution.push_back(s);
if (s.isGoal())
{
solved = true;
return f;
}
double fMin = inf;
MoveContainer& moves = s.successors(solution);
for (MoveContainer::const_iterator it = moves.begin();
it != moves.end(); ++it)
{
f = dfs(it->state(), g + it->cost());
if (solved)
{
return f;
}
if (f < fMin)
{
fMin = f;
}
}
solution.pop_back();
return fMin;
}
};
} // namespace search

#endif

tiles.cpp

///////////////////////////////////////////////////////////////////////////////
//
// tiles.cpp
//
///////////////////////////////////////////////////////////////////////////////

#include "search_IDAstar.h"#include <vector>
#include <algorithm> // find
#include <cstdlib> // abs

#include <iostream>
#include <ctime>

namespace // unnamed namespace
{
// Number of rows/columns in the sliding tile puzzle.
const int rows = 4;
const int columns = 4;
const int size = rows*columns;

// Manhattan distance heuristic.
int manhattan[size][size];

// A State is a configuration of a sliding tile puzzle.
class State
{
public:

// A state may be specified as a vector, where tiles[i] is the tile in
// the i-th position in row-major order, and the blank is specified as
// rows*columns == size == tiles.size().
typedef std::vector<int> Tiles;

// Constructor
State(const Tiles& tiles) :
tiles(tiles),
blank(0)
{
for (int i = 0; i < size; ++i)
{
if (tiles[i] == size)
{
blank = i;
break;
}
}
}

// Destructor
~State()
{
// empty
}

// Copy constructor
State(const State& copy) :
tiles(copy.tiles),
blank(copy.blank)
{
// empty
}

// Assignment operator
State& operator= (const State& rhs)
{
tiles = rhs.tiles;
blank = rhs.blank;
}

// Equality operator
bool operator== (const State& rhs)
{
for (int i = 0; i < size; ++i)
{
if (tiles[i] != rhs.tiles[i])
{
return false;
}
}
return true;
}

// Return admissible heuristic.
double h() const
{
int cost = 0;
for (int i = 0; i < size; ++i)
{
if (i != blank)
{
cost += manhattan[i][tiles[i] - 1];
}
}
return cost;
}

// Return true iff this state is a goal state.
bool isGoal() const
{
for (int i = 0; i < size; ++i)
{
if (tiles[i] != i + 1)
{
return false;
}
}
return true;
}

// Return successors of this state.
typedef search::Move<State> Move;
typedef std::list<Move> MoveContainer;
MoveContainer successors(std::list<State>& solution) const
{
MoveContainer moves;

// Move blank right.
if ((blank + 1)%columns != 0)
{
State s(*this);
s.tiles[blank] = tiles[blank + 1];
s.tiles[blank + 1] = size;
s.blank = blank + 1;
if (std::find(solution.begin(), solution.end(), s) ==
solution.end())
{
moves.push_back(Move(s, 1));
}
}

// Move blank up.
if (blank - columns >= 0)
{
State s(*this);
s.tiles[blank] = tiles[blank - columns];
s.tiles[blank - columns] = size;
s.blank = blank - columns;
if (std::find(solution.begin(), solution.end(), s) ==
solution.end())
{
moves.push_back(Move(s, 1));
}
}

// Move blank left.
if (blank%columns != 0)
{
State s(*this);
s.tiles[blank] = tiles[blank - 1];
s.tiles[blank - 1] = size;
s.blank = blank - 1;
if (std::find(solution.begin(), solution.end(), s) ==
solution.end())
{
moves.push_back(Move(s, 1));
}
}

// Move blank down.
if (blank + columns < size)
{
State s(*this);
s.tiles[blank] = tiles[blank + columns];
s.tiles[blank + columns] = size;
s.blank = blank + columns;
if (std::find(solution.begin(), solution.end(), s) ==
solution.end())
{
moves.push_back(Move(s, 1));
}
}
return moves;
}

Tiles tiles;
int blank;
};
} // unnamed namespace

int main()
{
// Initialize pre-computed Manhattan distance heuristic.
for (int i = 0; i < size; ++i)
{
for (int j = 0; j < size; ++j)
{
manhattan[i][j] = std::abs(i/columns - j/columns) +
std::abs(i%columns - j%columns);
}
}

// Get starting puzzle configuration.
std::cout << "Enter puzzle: ";
State::Tiles tiles;
for (int i = 0; i < size; ++i)
{
int t;
std::cin >> t;
tiles.push_back(t);
}

// Search for a solution.
search::IDAstar<State> ida;
std::clock_t tic = std::clock();
std::list<State> solution = ida.solve(State(tiles));
std::clock_t toc = std::clock();

// Display solution.
std::cout << "Solution in " << static_cast<int>(solution.size()) - 1 <<
" moves." << std::endl;
for (std::list<State>::iterator it = solution.begin(); it != solution.end(); ++it)
{
State::Tiles& tiles = (*it).tiles;
for (size_t i = 0; i < tiles.size(); ++i)
{
std::cout << tiles[i] << " ";
}
std::cout << std::endl;
}
std::cout << "Elapsed time = " <<
static_cast<double>(toc - tic)/CLOCKS_PER_SEC << " seconds." <<
std::endl;
}

Первая ошибка MoveContainer :: const_iterator я набрал auto, и это было временное исправление. Сначала я думаю, что это проблема с пространством имен или iostream, но это не так. Я компилирую с C ++ 11, C ++ 14 в Linux. Программа является примером алгоритма IDA * для решения 15 головоломок.

0

Решение

153:18: error: need 'typename' before 'MoveContainer:: const_iterator'
because 'MoveContainer' is a dependent scope

Этот говорит вам, что делать. + Изменить

for (MoveContainer::const_iterator it = moves.begin();

в

for (typename MoveContainer::const_iterator it = moves.begin();

Увидеть Где и почему я должен поставить «шаблон» а также «имяТипа» ключевые слова?

234:9: warning: no return statement in function returning non-void

Как говорится, ваш State::operator= отсутствует ответное заявление.

    // Assignment operator
State& operator= (const State& rhs)
{
tiles = rhs.tiles;
blank = rhs.blank;
return *this;
}

Или лучше не определять operator= вообще, по правилу нуля.

52:57: error: invalid initialization of non-const reference of type
'std::list<search::Move<{anonymous}::State> >&' from an rvalue of type
'{anonymous}::State::MoveContainer {aka
std::list<search::Move<{anonymous}::State> >}'

Прямо здесь:

MoveContainer& moves = s.successors(solution);

Вы пытаетесь инициализировать ссылку из функции, которая возвращает значение. Бросьте ссылку:

MoveContainer moves = s.successors(solution);

1

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

В шаблонах с ++, зависимые имена предполагается, что они являются значениями / функциями и могут быть проанализированы только как имя типа или шаблон, если вы явно указали его, используя ключевые слова типа или типа.

В этом случае, MoveContainer::const_iterator это имя, которое зависит от параметра шаблона MoveContainer, поэтому вам нужно сообщить компилятору, что это имя типа:

for (typename MoveContainer::const_iterator it = moves.begin();
it != moves.end(); ++it)
{
//...
}

Для получения дополнительной информации о том, почему это необходимо, см. этот ответ.

0

Сообщение об ошибке довольно явно:

error: need 'typename' before
'MoveContainer:: const_iterator' because 'MoveContainer' is a dependent scope

Если вы просто измените код на

for (typename MoveContainer::const_iterator it = moves.begin();
it != moves.end(); ++it)

тогда это должно скомпилироваться.

Причина в том, что для аргументов шаблона, таких как MoveContainer :: const_iterarator, компилятор не может определить, является ли const_iterator типом или статическим членом. Использование ‘typename’ говорит о том, что это тип. Старые компиляторы не были строгими в этом, и вы часто получаете эту ошибку при обновлении до более нового компилятора.

0

Понравилась статья? Поделить с друзьями:
  • Error need a single repository as argument
  • Error nck must be a 8 digit number yota
  • Error nc program does not contain any operations
  • Error nat tproxy lookup failed to locate original ips on local
  • Error nas introduced by coercion