简体   繁体   中英

C++:Use user-defined generic functions

I am now reading 《C++ Standard Library》.And I find something confused in chapter 5.7. As we know,we can write our own functions and algorithms to process elements of collections.Of course these operations may also be generic. Let's see a example.The following code defines a generic function that prints an optional string followed by all elements of the passed container.

template <class T>
inline void PRINT_ELEMENTS(const T& col1,const char *optcstr = "")
{
    typename T::const_iterator pos;
    for(pos = col1.begin();pos != col1.end();++pos)
        cout << *pos << " ";
    cout << endl;
}

And pos is declared as having the iterator type of the passed container type, typyname is necessary to specify that const_iterator is a type and not a value of type T.

I have several questions:

(1)When I erase typename in the code,it works well. See following code:

#include <iostream>
#include <vector>
#include <set>
#include <algorithm>

using namespace std;

int square (int value)
{
    return value*value;
}

template <class T>
inline void PRINT_ELEMENTS(const T& col1,const char *optcstr = "")
{
    /*typename T::const_iterator pos;*/
    T::const_iterator pos;

    for(pos = col1.begin();pos != col1.end();++pos)
        cout << *pos << " ";
    cout << endl;
}

int main()
{
    set<int>    coll1;
    vector<int> coll2;

    // insert elements from 1 to 9 into coll1
    for (int i=1; i<=9; ++i) {
        coll1.insert(i);
    }
    /*PRINT_ELEMENTS(coll1,"initialized: ");*/

    // transform each element from coll1 to coll2
    // - square transformed values
    transform (coll1.begin(),coll1.end(),    // source
                    back_inserter(coll2),    // destination
                    square);                      // operation

    PRINT_ELEMENTS(coll2,"squared:     ");
}

It works well.Its output is:在此处输入图像描述

Why?Is typename not necessary? And I don't very understand its function here. Could someone interpret to me?

(2) Why could not I use vector::iterator to output the elements like this:

#include <iostream>
#include <set>
#include <vector>
#include <algorithm>
using namespace std;

int main()
{
    set<int> intSet;
    vector<int> intVector2;

    for (int i = 1;i <= 10;++i)
        intSet.insert(i);

    transform(intSet.begin(),intSet.begin(),
        back_inserter(intVector2),
        negate<int>());

    vector<int>::iterator iter = intVector2.begin();
    for(;iter != intVector2.end();++iter)
        cout << *iter << endl;
}

It outputs nothing.I use Visual Studio 2008 to run my code. Could someone help me?Thanks a lot.

typename isn't necessary because some versions of Visual Studio do not conform to the Standard. Newer versions and other compilers are more strict about this and your code will fail to compile there without it.

Your second example does not work because you passed begin() and begin() , not begin() and end() .

transform(intSet.begin(),intSet.begin(),

Whoops.

(1)

typename helps disambiguate its operand as a type in certain situations.

Most prominently seems to be in the scope of a class declaration:

class X
{
    ...
    typename Y::Z w; // necessary
};

(2)

There is a typo...

-    transform(intSet.begin(),intSet.begin(),
    back_inserter(intVector2),
    negate<int>());


+    transform(intSet.begin(),intSet.end(),
    back_inserter(intVector2),
    negate<int>());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM