星海's Blog

老头初学编程
我的doxygenfile
gsoap 2.8.x 的中文第一字节乱码问题。

C++ Templates FAQ(转)

星海 posted @ 2013年1月11日 10:26 in 通用知识 , 2042 阅读

转自   http://womble.decadent.org.uk/c++/template-faq.html

 

C++ Templates FAQ

This is not an introduction or a reference manual to templates. It deals with some of the more complex yet still common problems with templates.

Other information

Templates are an essential part of modern C++, and any good recent introduction to C++ should cover them. If you lack such an introductory text, I recommend you read either Koenig & Moo, Accelerated C++ (Addison-Wesley, ISBN 020170353X, US sellers, UK sellers) or Stroustrup, The C++ Programming Language 3rd ed. (Addison Wesley, ISBN 0201700735, US sellers, UK sellers), depending on your prior programming experience.

Some basic questions about templates are answered by Marshall Cline's C++ FAQ Lite.

For in-depth reference, see Vandevoorde & Josuttis, C++ Templates: The Complete Guide (Addison-Wesley, ISBN 0201734842, US sellers, UK sellers).

Acknowledgement

Daveed Vandevoorde kindly reviewed this FAQ for correctness.

Contents

  1. Why do I get a syntax error when I use a type that's a member of a template in the definition of another template?
  2. My compiler says that a member of a base class template is not defined in a derived class template. Why is it not inherited?
  3. Is it possible to specialise a member function of a class template without specialising the whole template?
  4. Why doesn't Visual C++ 6 accept my definition of a class template's member function outside of the class definition?
  5. Why does every instance of my function template do the same thing under Visual C++ 6?
  6. Why do I need to add "template" and "typename" in the bodies of template definitions?
  7. What is two-phase name lookup?
  8. What are dependent names?
  9. What are non-dependent names?
  10. Which rules do the various C++ implementations apply for name resolution in templates?
  11. Is there a difference between a function template and a template function, or between a class template and a template class?
  12. What does the error message "specialization of ... in different namespace" mean?
  13. What does the error message "duplicate explicit instanatiation of ..." mean?
  1. Q: Why do I get a syntax error when I use a type that's a member of a class template in the definition of another template?

    template<typename T>
    struct first {
        typedef T * pointer;
    };
    
    template<typename T>
    class second {
        first<T>::pointer p; // syntax error
    };

    A: In a template, the name of a member of another class that depends on its template parameter(s) (first<T>::pointer in this example, dependent on the T parameter) is a dependent name that is not looked-up immediately. To tell the compiler that it is meant to refer to a type and not some other sort of member, you must add the keyword typename before it.

  2. Q: My compiler says that a member of a base class template is not defined in a derived class template. Why is it not inherited?

    template<typename T>
    class base {
    public:
        void base_func();
    };
    
    template<typename T>
    class derived : public base<T> {
    public:
        void derived_func()
        {
            base_func(); // error: base_func not defined
        }
    };

    A: It is inherited. However, the standard says that unqualified names in a template are generally non-dependent and must be looked up when the template is defined. Since the definition of a dependent base class is not known at that time (there may be specialisations of the base class template that have not yet been seen), unqualified names are never resolved to members of the dependent base class. Where names in the template are supposed to refer to base class members or to indirect base classes, they can either be made dependent by qualifying them or brought into the template's scope with a using-declaration. In the example, this could be achieved by replacing the call to base_func() with this->base_func() or base<T>::base_func(), or by adding the declaration using base<T>::base_func;.

  3. Q: Is it possible to specialise a member function of a class template without specialising the whole template?

    A: According to the standard, you can declare a full specialisation of a member function of a class template like this:

    template<typename T>
    class my_class {
    public:
        bool func();
        // other functions
    };
    
    template<>
    bool my_class<int>::func();

    Unfortunately not all compilers support this.

  4. Q: Why doesn't Visual C++ 6 accept my definition of a member function template outside of the class definition?

    class my_class {
    public:
        template<typename T> void func();
    };
    
    template<typename T>
    void my_class::func()
    {
        // implementation
    }

    A: This is a limitation of Visual C++ 6 which was fixed in version 7.

  5. Q: Why does every instance of my function template do the same thing under Visual C++ 6?

    template<typename T>
    std::size_t my_sizeof()
    {
        return sizeof(T);
    }

    A: This is a bug in Visual C++ 6 which was fixed in version 7. It distinguishes function template instances only by their function parameter types, not by their template arguments, so unless all template parameters are used in the declaration of the function parameter types it is possible for some instances of the template to be discarded and other instances used instead. As a workaround, you can use the template parameters to define optional function parameters that are never used:

    template<typename T>
    std::size_t my_sizeof(T * = 0)
    {
        return sizeof(T);
    }
  6. Q: Why do I need to add "template" and "typename" in the bodies of template definitions?

    A: The meaning of a name used in a template definition may depend upon the template parameters, in which case it cannot automatically be determined when the template is defined. Early implementations of templates postponed resolution of all names used in a template to the time of instantiation, but this was found to be error-prone. It made it impossible to parse template definitions completely because many C++ syntax rules depend on distinguishing between names that refer to objects or functions, names that refer to types, and names that refer to templates.

    Later implementations parse templates as soon as they are defined. They require the programmer to specify which dependent names refer to types or templates, so that they can parse the templates without ambiguity. Where a dependent name is intended to refer to a type, it must generally be prefixed by the keyword typename. (This is not necessary when it is used in the list of base classes of a class template, since only type names can be used there.) Where a dependent qualified name or a prefix of such a name is intended to refer to a template, the last component of it must be prefixed by the keyword template. Note that some implementations may consider names to be dependent where the standard says they are non-dependent, and may therefore require additional uses of typename and template.

    template<typename Alloc>
    class container_helper
    {
        typedef Alloc::value_type value_type;
            // ill-formed: Alloc::value_type is assumed to be an object or function
        typedef typename Alloc::value_type value_type;
            // OK: Alloc::pointer is properly disambiguated
        typedef Alloc::typename value_type value_type;
            // ill-formed: "typename" must precede the whole qualified name
        typedef std::pair<value_type, value_type> element_type;
            // OK: value_type is resolved in the immediate scope
        typedef typename Alloc::rebind<element_type>::other element_allocator;
            // ill-formed: Alloc::rebind is assumed to be an object or function
        typedef typename template Alloc::rebind<element_type>::other element_allocator;
            // ill-formed: "template" must precede the last component of the
            // template name
        typedef typename Alloc::template rebind<element_type>::other element_allocator;
            // OK: rebind is properly disambiguated
    };
    
    template<typename T, typename Alloc = std::allocator<T> >
    class my_container : private container_helper<Alloc>::element_allocator
            // OK: container_helper<Alloc>::element_allocator cannot be resolved
            // but base names are assumed to be type names
    {
    };
  7. Q: What is two-phase name lookup?

    A: This is the process specified by the standard for looking up names in templates. It is called "two-phase name lookup" because it divides names used in a template into two categories (dependent and non-dependent) that are resolved at different times. It was introduced into the draft standard some time in 1993 or 1994 but unfortunately has not been implemented by many vendors until quite recently. It makes name resolution more reliable, but is incompatible with a lot of older template code.

    The rules specifying exactly which names are considered dependent and which non-dependent are mostly intuitive, but with some corner cases. They can be found in section 14.6 of the standard.

  8. Q: What are dependent names?

    A: Dependent names are names whose definitions are considered to depend upon the template parameters and for which there is no declaration within the template definition. They are resolved only when the template is instantiated. Those that are intended to refer to types or templates may require disambiguation.

    If the resolution of a dependent function name uses argument-dependent lookup, declarations in the arguments' namespaces that are visible at the point of instantiation will be considered as well as declarations visible at the point of definition. (The former is normally a superset of the latter, but may not be.)

  9. Q: What are non-dependent names?

    A: Non-dependent names are those names that are considered not to depend upon the template parameters, plus the name of the template itself and names declared within it (members, friends and local variables). They are resolved when the template is defined, in the normal way, and do not require disambiguation.

  10. Q: Which rules do the various C++ implementations apply for name resolution in templates?

    A: I have divided implementations into three categories: CFront, those that resolve all names at the point of instantiation, like CFront did; intermediate, those that parse templates more fully, resolving some names at the point of definition and requiring disambiguation of others; and standard, those that use the standard rules. Note that there is a lot of variation among the "intermediate" implementations.

    Implementation Versions and options Name lookup rules
    Comeau C++ 4.x, CFront mode CFront
    4.x, relaxed mode;
    4.0-4.2.43, strict mode
    intermediate
    4.2.44-4.3.3, strict mode standard
    GNU C++ (g++) 2.8-3.3 intermediate
    3.4-4.1 standard
    Metrowerks CodeWarrior 8-9, default intermediate (?)
    8-9, -iso-templates standard
    Microsoft Visual C++ 6.0 CFront
    7.0-8.0 (VS.NET 2002-2005) intermediate

    (This table is acknowledged to be incomplete and possibly incorrect in some details. Let me know if you have more information.)

  11. Q: Is there a difference between a function template and a template function, or between a class template and a template class?

    A: The term "function template" refers to a kind of template. The term "template function" is sometimes used to mean the same thing, and sometimes to mean a function instantiated from a function template. This ambiguity is best avoided by using "function template" for the former and something like "function template instance" or "instance of a function template" for the latter. Note that a function template is not a function. The same distinction applies to "class template" versus "template class".

    Note that the 1998 C++ standard used the terms "template class" and "template function" in some places, but this was corrected in the 2003 version.

  12. Q: What does the error message "specialization of ... in different namespace" mean?

    A: This means that the code appears to be defining a template specialisation, but it names a template that was defined in a different namespace. This is not valid, though some older versions of g++ accept it. Every declaration for a template must be placed in the same namespace, just like repeated declarations of any other named entity.

  13. Q: What does the error message "duplicate explicit instantiation of ..." mean?

    A: An explicit instantiation of a function or class template is a definition of a function or class. It is an error to define either of those more than once in a translation unit, whether or not they are instantiated from a template. It is also an error to define a function more than once in an entire program unless it is defined as inline.


Ben Hutchings

Last modified: Mon Dec 13 13:34:12 GMT 2010

Avatar_small
λ 说:
2013年1月26日 01:01

我×,大叔的英语水平进步了

Avatar_small
星海 说:
2013年1月27日 18:52

进步个P啊。。。。

词典+蒙+谷歌。。。


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter