Templates and Macros plus more...

This is a discussion on Templates and Macros plus more... within the C++ Programming forums, part of the General Programming Boards category; I have a couple of questions about various things that have had me puzzled. Not that I really need to ...

  1. #1
    Registered User
    Join Date
    Aug 2006
    Posts
    14

    Templates and Macros plus more...

    I have a couple of questions about various things that have had me puzzled. Not that I really need to know, but I'm just curious, thats all...

    1. It is possible to write a macro called JOIN that joins macro arguments together such as
    Code:
    #include <iostream>
    #define JOIN(a,b) a ## b
    int main() {
        JOIN(std::co,ut <<) "hello"; // will print "hello"
    }
    Is it possible to modify these input arguments in the macro. Ie is a macro REVERSE possible eg
    Code:
    #include <iostream>
    #define REVERSE(a) ???? // is this possible?
    int main() {
        REVERSE(<< tuoc::dts) "hello"; // prints hello
    }
    2. I have written a function to calculate the average of a vector of numbers. It is templated so that it works on any type of value. However is it possible to check if the template type has an addition and division operator and if not, print a compile error message?
    My code:
    Code:
    template <typename T>
    T average<T>(std::vector<T> numbers)
    {
        // #if T does not have + and / , #error "cannot compute average"
        double sum = std::accumulate(numbers.begin(), numbers.end(), 0);
        return sum / numbers.size();
    }
    3. In some functions in the boost library, I have noticed that they appear to return a type (eg boost::result_of). How is this possible?
    Example:
    Code:
    #include <boost/utility/result_of.hpp>
    #include <iostream>
    template<typename Function>
    std::string typeTest(Function f) {
        boost::result_of<Function()>::type output;  // how does this work?
        return typeid(output).name();
    }
    
    
    int main()
    {
        std::cout << typeTest(&main); // prints "int"
        std::cin.get();
    }
    4. How does typeid work internally? Is the answer computed at runtime or compile time? Also, does using it result in extra memory being used to store type information in classes?

    5. Is it possible to have a function return a stack object without the created stack object being copied and deleted?
    Eg
    Code:
    #include <iostream>
    class TestClass {
    public:
        int value;
    
        TestClass() {
            value = 0;
            std::cout << "Constructor\n";
        }
    
        TestClass(TestClass& rhs) {
            value = rhs.value;
            std::cout << "Copy Constructor\n";
        }
    
        void setValue(int num) {
            value = num;
        }
    
        ~TestClass() {
            std::cout << "deconstructor\n";
        }
    };
    
    TestClass test() {
        TestClass tc;
        tc.setValue(3);
        return tc;
    }
    
    void test2() {
        TestClass t = test();
    }
    
    int main() {
        test2();
        std::cin.get();
    	return 0;
    }
    Output:
    Code:
    Constructor
    Copy Constructor
    deconstructor
    deconstructor
    There doesn't seem to be any reason for the compiler to copy the object as it is only being used in the caller function.

  2. #2
    Registered User
    Join Date
    Jan 2005
    Posts
    7,328
    2. The compiler will give you an error. After fixing your code and testing with string, VC++ 7.1 gave this message (among others):
    Code:
    error C2676: binary '/' : 'std::string' does not define this operator or a
                 conversion to a type acceptable to the predefined operator
    5. Many compilers will optimize the copy away (with RVO - Return Value Optimization). Try it with optimizations enabled (e.g. in Release Build or with -O2) and see if the copy constructor is called. I don't know of any way to force it.

  3. #3
    Registered User
    Join Date
    Mar 2006
    Posts
    725
    There doesn't seem to be any reason for the compiler to copy the object as it is only being used in the caller function.
    There doesn't seem to be any reason for the compiler to not copy the object, since that's what it's supposed to do.
    5. A stack is implemented as, well, a stack. You can pass storage for the return value in by reference, or use dynamic memory. Compilers may try to optimize this, but if your classes get just a little complicated, they'll get lost. Yeah, compilers are dumb. Deal with it.
    4. "When typeid is applied to classes typeid uses the run-time type information to keep track of the type of dynamic objects." - CPlusPlus.com
    3. Boost is open source.
    2. The compiler will do it anyway, if you try to use + and /, like std::accumulate and your function do.
    1. C++ is not for you. Try Lisp instead.
    Code:
    #include <stdio.h>
    
    void J(char*a){int f,i=0,c='1';for(;a[i]!='0';++i)if(i==81){
    puts(a);return;}for(;c<='9';++c){for(f=0;f<9;++f)if(a[i-i%27+i%9
    /3*3+f/3*9+f%3]==c||a[i%9+f*9]==c||a[i-i%9+f]==c)goto e;a[i]=c;J(a);a[i]
    ='0';e:;}}int main(int c,char**v){int t=0;if(c>1){for(;v[1][
    t];++t);if(t==81){J(v[1]);return 0;}}puts("sudoku [0-9]{81}");return 1;}

  4. #4
    Registered User
    Join Date
    Aug 2006
    Posts
    14
    Thanks for the answers. I wasn't sure if a lot of the stuff I wanted was even possible.

    1. Lisp is great. Its unfortunate that c macros aren't as good apparently

    2. The main reason I wanted this to happen is so that the error occurs in the caller code, not my code. Then, if a template function is used inside another template functions, it becomes very difficult to track the original cause of the error as the error message generated is huge. For example
    Code:
    #include <iostream>
    #include <vector>
    #include <numeric>
    #include <string>
    
    using std::vector;
    using std::ostream;
    /* very simple class */
    class Lame {
    
        friend ostream& operator <<(ostream &os, const Lame &obj)
        {
            return os << "Lame object\n";
        }
    public:
        //Lame operator+(Lame& a) {
        //    return Lame();
        //} uncommenting this makes the code work
        
    
    };
    /* sums all the elements in the vector. Only needs + defined
    eg it will work with a string */
    template <typename T>
    T sumAll(vector<T> v)
    {
        return std::accumulate(v.begin(), v.end(), T());
    }
    
    /* Sums all the elements but each element is summed
    multiple times
    */
    template <typename T>
    T sumAllRepeat(vector<T> numbers, unsigned int times)
    {
        vector<T> allN;
        for(unsigned int i = 0; i < numbers.size(); i++) {
            for(unsigned int j = 0; j < times; j++) {
                allN.push_back(numbers[i]);
            }
        }
        return sumAll(allN);
    }
    
    
    int main() {
    
    
        vector<std::string> v1;
        v1.push_back("a");
        v1.push_back("b");
        std::cout << sumAllRepeat(v1, 4); // this works (aaaabbbb)
    
    
        vector<Lame> v2;
        v2.push_back(Lame());
        v2.push_back(Lame());
        std::cout <<  sumAll(v2); // this creates an error
        
    
        std::cin.get();
    	return 0;
    }
    The code compiles and works correctly without the red line, but with it it generates the compile error message:


    PHP Code:
    Compiling...
    OneFileTest.cpp
    d
    :\program files\microsoft visual studio 8\vc\include\numeric(23) : error C2784'std::basic_string<_Elem,_Traits,_Alloc> std::operator +(const std::basic_string<_Elem,_Traits,_Alloc> &,const _Elem)' could not deduce template argument for 'const std::basic_string<_Elem,_Traits,_Alloc> &' from 'Lame'
            
    d:\program files\microsoft visual studio 8\vc\include\string(61) : see declaration of 'std::operator +'
            
    d:\program files\microsoft visual studio 8\vc\include\numeric(31) : see reference to function template instantiation '_Ty std::_Accumulate<std::_Vector_iterator<_Ty,_Alloc>,_Ty>(_InIt,_InIt,_Ty)' being compiled
            with
            
    [
                
    _Ty=Lame,
                
    _Alloc=std::allocator<Lame>,
                
    _InIt=std::_Vector_iterator<Lame,std::allocator<Lame>>
            ]
            
    c:\programming\cpp\onefiletest.cpp(27) : see reference to function template instantiation '_Ty std::accumulate<std::_Vector_iterator<_Ty,_Alloc>,Lame>(_InIt,_InIt,_Ty)' being compiled
            with
            
    [
                
    _Ty=Lame,
                
    _Alloc=std::allocator<Lame>,
                
    _InIt=std::_Vector_iterator<Lame,std::allocator<Lame>>
            ]
            
    c:\programming\cpp\onefiletest.cpp(58) : see reference to function template instantiation 'T sumAll<Lame>(std::vector<_Ty>)' being compiled
            with
            
    [
                
    T=Lame,
                
    _Ty=Lame
            
    ]
    d:\program files\microsoft visual studio 8\vc\include\numeric(23) : error C2784'std::basic_string<_Elem,_Traits,_Alloc> std::operator +(const std::basic_string<_Elem,_Traits,_Alloc> &,const _Elem *)' could not deduce template argument for 'const std::basic_string<_Elem,_Traits,_Alloc> &' from 'Lame'
            
    d:\program files\microsoft visual studio 8\vc\include\string(51) : see declaration of 'std::operator +'
    d:\program files\microsoft visual studio 8\vc\include\numeric(23) : error C2784'std::basic_string<_Elem,_Traits,_Alloc> std::operator +(const _Elem,const std::basic_string<_Elem,_Traits,_Alloc> &)' could not deduce template argument for 'const std::basic_string<_Elem,_Traits,_Alloc> &' from 'Lame'
            
    d:\program files\microsoft visual studio 8\vc\include\string(41) : see declaration of 'std::operator +'
    d:\program files\microsoft visual studio 8\vc\include\numeric(23) : error C2784'std::basic_string<_Elem,_Traits,_Alloc> std::operator +(const _Elem *,const std::basic_string<_Elem,_Traits,_Alloc> &)' could not deduce template argument for 'const _Elem *' from 'Lame'
            
    d:\program files\microsoft visual studio 8\vc\include\string(31) : see declaration of 'std::operator +'
    d:\program files\microsoft visual studio 8\vc\include\numeric(23) : error C2784'std::basic_string<_Elem,_Traits,_Alloc> std::operator +(const std::basic_string<_Elem,_Traits,_Alloc> &,const std::basic_string<_Elem,_Traits,_Alloc> &)' could not deduce template argument for 'const std::basic_string<_Elem,_Traits,_Alloc> &' from 'Lame'
            
    d:\program files\microsoft visual studio 8\vc\include\string(21) : see declaration of 'std::operator +'
    d:\program files\microsoft visual studio 8\vc\include\numeric(23) : error C2784'std::_Vb_iterator<_MycontTy> std::operator +(_Vb_iterator<_MycontTy>::difference_type,std::_Vb_iterator<_MycontTy>)' could not deduce template argument for 'std::_Vb_iterator<_MycontTy>' from 'Lame'
            
    d:\program files\microsoft visual studio 8\vc\include\vector(1800) : see declaration of 'std::operator +'
    d:\program files\microsoft visual studio 8\vc\include\numeric(23) : error C2784'std::_Vb_const_iterator<_MycontTy> std::operator +(_Vb_const_iterator<_MycontTy>::difference_type,std::_Vb_const_iterator<_MycontTy>)' could not deduce template argument for 'std::_Vb_const_iterator<_MycontTy>' from 'Lame'
            
    d:\program files\microsoft visual studio 8\vc\include\vector(1695) : see declaration of 'std::operator +'
    d:\program files\microsoft visual studio 8\vc\include\numeric(23) : error C2784'std::_Vector_iterator<_Ty,_Alloc> std::operator +(_Vector_iterator<_Ty,_Alloc>::difference_type,std::_Vector_iterator<_Ty,_Alloc>)' could not deduce template argument for 'std::_Vector_iterator<_Ty,_Alloc>' from 'Lame'
            
    d:\program files\microsoft visual studio 8\vc\include\vector(396) : see declaration of 'std::operator +'
    d:\program files\microsoft visual studio 8\vc\include\numeric(23) : error C2784'std::_Vector_const_iterator<_Ty,_Alloc> std::operator +(_Vector_const_iterator<_Ty,_Alloc>::difference_type,std::_Vector_const_iterator<_Ty,_Alloc>)' could not deduce template argument for 'std::_Vector_const_iterator<_Ty,_Alloc>' from 'Lame'
            
    d:\program files\microsoft visual studio 8\vc\include\vector(264) : see declaration of 'std::operator +'
    d:\program files\microsoft visual studio 8\vc\include\numeric(23) : error C2784'std::_String_iterator<_Elem,_Traits,_Alloc> std::operator +(_String_iterator<_Elem,_Traits,_Alloc>::difference_type,std::_String_iterator<_Elem,_Traits,_Alloc>)' could not deduce template argument for 'std::_String_iterator<_Elem,_Traits,_Alloc>' from 'Lame'
            
    d:\program files\microsoft visual studio 8\vc\include\xstring(438) : see declaration of 'std::operator +'
    d:\program files\microsoft visual studio 8\vc\include\numeric(23) : error C2784'std::_String_const_iterator<_Elem,_Traits,_Alloc> std::operator +(_String_const_iterator<_Elem,_Traits,_Alloc>::difference_type,std::_String_const_iterator<_Elem,_Traits,_Alloc>)' could not deduce template argument for 'std::_String_const_iterator<_Elem,_Traits,_Alloc>' from 'Lame'
            
    d:\program files\microsoft visual studio 8\vc\include\xstring(298) : see declaration of 'std::operator +'
    d:\program files\microsoft visual studio 8\vc\include\numeric(23) : error C2784'std::reverse_iterator<_RanIt> std::operator +(_Diff,const std::reverse_iterator<_RanIt> &)' could not deduce template argument for 'const std::reverse_iterator<_RanIt> &' from 'Lame'
            
    d:\program files\microsoft visual studio 8\vc\include\xutility(1809) : see declaration of 'std::operator +'
    d:\program files\microsoft visual studio 8\vc\include\numeric(23) : error C2676binary '+' 'Lame' does not define this operator or a conversion to a type acceptable to the predefined operator 




    Note how hard it is to determine the cause of the compile error: the main method is not mentioned once in the error message but is the method that contained the bug.

    4.
    When typeid is applied to classes typeid uses the run-time type information to keep track of the type of dynamic objects
    Does this mean that for every object, a pointer for that object is kept to point to the rtti information? I understand that that already occurs for derived classes, but what about classes like vector and string, as well as primitive types? I'm just concerned that using typeid will force the compiler to use much more memory than it needs to.

    5. Oh well. I mainly needed it for efficiency but it doesn't really matter

  5. #5
    Registered User
    Join Date
    Jun 2005
    Posts
    6,341
    Quote Originally Posted by Monkeymagic
    The code compiles and works correctly without the red line, but with it it generates the compile error message:
    PHP Code:
    Compiling...
    OneFileTest.cpp
    d
    :\program files\microsoft visual studio 8\vc\include\numeric(23) : error C2784'std::basic_string<_Elem,_Traits,_Alloc> std::operator +(const std::basic_string<_Elem,_Traits,_Alloc> &,const _Elem)' could not deduce template argument for 'const std::basic_string<_Elem,_Traits,_Alloc> &' from 'Lame'
            
    d:\program files\microsoft visual studio 8\vc\include\string(61) : see declaration of 'std::operator +'
            
    d:\program files\microsoft visual studio 8\vc\include\numeric(31) : see reference to function template instantiation '_Ty std::_Accumulate<std::_Vector_iterator<_Ty,_Alloc>,_Ty>(_InIt,_InIt,_Ty)' being compiled
            with
            
    [
                
    _Ty=Lame,
                
    _Alloc=std::allocator<Lame>,
                
    _InIt=std::_Vector_iterator<Lame,std::allocator<Lame>>
            ]
            
    c:\programming\cpp\onefiletest.cpp(27) : see reference to function template instantiation '_Ty std::accumulate<std::_Vector_iterator<_Ty,_Alloc>,Lame>(_InIt,_InIt,_Ty)' being compiled
            with
            
    [
                
    _Ty=Lame,
                
    _Alloc=std::allocator<Lame>,
                
    _InIt=std::_Vector_iterator<Lame,std::allocator<Lame>>
            ]
            
    c:\programming\cpp\onefiletest.cpp(58) : see reference to function template instantiation 'T sumAll<Lame>(std::vector<_Ty>)' being compiled
            with
            
    [
                
    T=Lame,
                
    _Ty=Lame
            
    ]
    d:\program files\microsoft visual studio 8\vc\include\numeric(23) : error C2784'std::basic_string<_Elem,_Traits,_Alloc> std::operator +(const std::basic_string<_Elem,_Traits,_Alloc> &,const _Elem *)' could not deduce template argument for 'const std::basic_string<_Elem,_Traits,_Alloc> &' from 'Lame'
            
    d:\program files\microsoft visual studio 8\vc\include\string(51) : see declaration of 'std::operator +'
    d:\program files\microsoft visual studio 8\vc\include\numeric(23) : error C2784'std::basic_string<_Elem,_Traits,_Alloc> std::operator +(const _Elem,const std::basic_string<_Elem,_Traits,_Alloc> &)' could not deduce template argument for 'const std::basic_string<_Elem,_Traits,_Alloc> &' from 'Lame'
            
    d:\program files\microsoft visual studio 8\vc\include\string(41) : see declaration of 'std::operator +'
    d:\program files\microsoft visual studio 8\vc\include\numeric(23) : error C2784'std::basic_string<_Elem,_Traits,_Alloc> std::operator +(const _Elem *,const std::basic_string<_Elem,_Traits,_Alloc> &)' could not deduce template argument for 'const _Elem *' from 'Lame'
            
    d:\program files\microsoft visual studio 8\vc\include\string(31) : see declaration of 'std::operator +'
    d:\program files\microsoft visual studio 8\vc\include\numeric(23) : error C2784'std::basic_string<_Elem,_Traits,_Alloc> std::operator +(const std::basic_string<_Elem,_Traits,_Alloc> &,const std::basic_string<_Elem,_Traits,_Alloc> &)' could not deduce template argument for 'const std::basic_string<_Elem,_Traits,_Alloc> &' from 'Lame'
            
    d:\program files\microsoft visual studio 8\vc\include\string(21) : see declaration of 'std::operator +'
    d:\program files\microsoft visual studio 8\vc\include\numeric(23) : error C2784'std::_Vb_iterator<_MycontTy> std::operator +(_Vb_iterator<_MycontTy>::difference_type,std::_Vb_iterator<_MycontTy>)' could not deduce template argument for 'std::_Vb_iterator<_MycontTy>' from 'Lame'
            
    d:\program files\microsoft visual studio 8\vc\include\vector(1800) : see declaration of 'std::operator +'
    d:\program files\microsoft visual studio 8\vc\include\numeric(23) : error C2784'std::_Vb_const_iterator<_MycontTy> std::operator +(_Vb_const_iterator<_MycontTy>::difference_type,std::_Vb_const_iterator<_MycontTy>)' could not deduce template argument for 'std::_Vb_const_iterator<_MycontTy>' from 'Lame'
            
    d:\program files\microsoft visual studio 8\vc\include\vector(1695) : see declaration of 'std::operator +'
    d:\program files\microsoft visual studio 8\vc\include\numeric(23) : error C2784'std::_Vector_iterator<_Ty,_Alloc> std::operator +(_Vector_iterator<_Ty,_Alloc>::difference_type,std::_Vector_iterator<_Ty,_Alloc>)' could not deduce template argument for 'std::_Vector_iterator<_Ty,_Alloc>' from 'Lame'
            
    d:\program files\microsoft visual studio 8\vc\include\vector(396) : see declaration of 'std::operator +'
    d:\program files\microsoft visual studio 8\vc\include\numeric(23) : error C2784'std::_Vector_const_iterator<_Ty,_Alloc> std::operator +(_Vector_const_iterator<_Ty,_Alloc>::difference_type,std::_Vector_const_iterator<_Ty,_Alloc>)' could not deduce template argument for 'std::_Vector_const_iterator<_Ty,_Alloc>' from 'Lame'
            
    d:\program files\microsoft visual studio 8\vc\include\vector(264) : see declaration of 'std::operator +'
    d:\program files\microsoft visual studio 8\vc\include\numeric(23) : error C2784'std::_String_iterator<_Elem,_Traits,_Alloc> std::operator +(_String_iterator<_Elem,_Traits,_Alloc>::difference_type,std::_String_iterator<_Elem,_Traits,_Alloc>)' could not deduce template argument for 'std::_String_iterator<_Elem,_Traits,_Alloc>' from 'Lame'
            
    d:\program files\microsoft visual studio 8\vc\include\xstring(438) : see declaration of 'std::operator +'
    d:\program files\microsoft visual studio 8\vc\include\numeric(23) : error C2784'std::_String_const_iterator<_Elem,_Traits,_Alloc> std::operator +(_String_const_iterator<_Elem,_Traits,_Alloc>::difference_type,std::_String_const_iterator<_Elem,_Traits,_Alloc>)' could not deduce template argument for 'std::_String_const_iterator<_Elem,_Traits,_Alloc>' from 'Lame'
            
    d:\program files\microsoft visual studio 8\vc\include\xstring(298) : see declaration of 'std::operator +'
    d:\program files\microsoft visual studio 8\vc\include\numeric(23) : error C2784'std::reverse_iterator<_RanIt> std::operator +(_Diff,const std::reverse_iterator<_RanIt> &)' could not deduce template argument for 'const std::reverse_iterator<_RanIt> &' from 'Lame'
            
    d:\program files\microsoft visual studio 8\vc\include\xutility(1809) : see declaration of 'std::operator +'
    d:\program files\microsoft visual studio 8\vc\include\numeric(23) : error C2676binary '+' 'Lame' does not define this operator or a conversion to a type acceptable to the predefined operator 


    Note how hard it is to determine the cause of the compile error: the main method is not mentioned once in the error message but is the method that contained the bug.
    You just need to learn to read the error messages. Granted, it's not as easy as it could be. But the first few lines make it obvious the cause is related to class Lame, and the last line actually describes the real cause of the error.

    In any event, you might want to do some digging on traits classes. Traits classes are used (in the STL and, incidentally by boost) to enforce conditions that are required for a class to be used with particular conditions. For example, supporting particular conversions. It would probably be possible to use such a technique to enforce a requirement that an expression "a+b" is valid for your type.

    Quote Originally Posted by Monkeymagic
    Does this mean that for every object, a pointer for that object is kept to point to the rtti information? I understand that that already occurs for derived classes, but what about classes like vector and string, as well as primitive types? I'm just concerned that using typeid will force the compiler to use much more memory than it needs to.
    I wouldn't worry about it.

    It depends on the compiler and how it implements classes and, naturally, the typeid operator i.e. it's an issue related to quality of implementation of your compiler. Most classes will need to be associated with some information about their type, to support operators like typeid() and dynamic_cast<>. That overhead will normally be there regardless of whether you use those operators, as the compiler can't judge if some other function (eg in another source) will use those operators. So, it is probably something that compiler vendors will optimise very carefully to minimise memory or performance overhead.

    Quote Originally Posted by Monkeymagic
    5. Oh well. I mainly needed it for efficiency but it doesn't really matter
    It is possible to avoid temporaries by careful design. For example, using a += b will avoid a temporary that a = a+b; would introduce by default (and that the compiler would have trouble eliminating for user-defined types, as there is not necessarily a 1-1 correspondence between the += operator and + operator).

    You might want to look ip the blitz++ numeric library. It is a C++ template library designed around numerics. It also uses some pretty clever techniques to avoid temporaries (as some of the objects they pass around, such as large matrices) are very costly to copy.

    The C++ standard explicitly makes some allowances so that the RVO (and some other optimisations of temporaries out of existance) are feasible. For example, a temporary does not need to be created if the ONLY way of detecting its existance is by tracking constructor and destructor calls. However, again we get in the domain of quality of implementation of compilers: it is up to the compiler vendor as to whether they do that.

  6. #6
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,893
    Quote Originally Posted by Monkeymagic
    1. It is possible to write a macro called JOIN that joins macro arguments together [...] JOIN(std::co,ut <<) "hello";
    Yes and no. The result of ## must be a valid preprocessor token, which "std::cout <<" isn't - that's two tokens.
    You can join two tokens together if, and only if, the result is a valid token again.

    Is it possible to modify these input arguments in the macro. Ie is a macro REVERSE possible
    No. The only things you can play with are whitespace, commas and parentheses in the arguments.

    2. I have written a function to calculate the average of a vector of numbers. It is templated so that it works on any type of value. However is it possible to check if the template type has an addition and division operator and if not, print a compile error message?
    See the Boost.Concept_Check library. See also BOOST_STATIC_ASSERT. See also the native C++ concepts coming up in the next standard.
    http://www.generic-programming.org/software/ConceptGCC/

    No matter how you turn it, however, until we actually have proper concept support, the error messages will be ugly.

    3. In some functions in the boost library, I have noticed that they appear to return a type (eg boost::result_of). How is this possible?
    Those are meta-functions. They are "executed" by the compiler. In technical terms, they're just template structs with a nested "type" typedef that is the "result" of the "function".
    To learn more about this stuff, read "C++ Template Metaprogramming" by David Abrahams and Aleksey Gurtovoy.

    4. How does typeid work internally?
    Depends on the compiler.

    Is the answer computed at runtime or compile time?
    Depends. If the answer can be calculated at compile time, it is. If not, i.e. when using it on an expression that results in a reference to a polymorphic class (a class with at least one virtual function), then it's calculated at runtime.

    Also, does using it result in extra memory being used to store type information in classes?
    Again, depends on the compiler. Many compiler require you to explicitly enable RTTI before you can use typeid. Some allow you to disable it. If it's enabled, then the additional memory is required for any polymorphic class, no matter if you use typeid or not. For other types, additional memory in the executable may or may not be required, depending on the compiler and whether you use typeid on the type or not.

    5. Is it possible to have a function return a stack object without the created stack object being copied and deleted?
    No. A stack object goes out of scope, and the programmer can't do anything about it. End of story.
    On the other hand, the compiler might do something about it. See RVO and NRVO. But don't rely on this behaviour, because like all optimizations, it's optional.

    There doesn't seem to be any reason for the compiler to copy the object as it is only being used in the caller function.
    No, strictly speaking, a different object is used in the caller function.

    1. Lisp is great. Its unfortunate that c macros aren't as good apparently
    Perhaps unfortunate. Perhaps fortunate. Lisp macros have great potential for abuse - even those part of the Common Lisp standard. (For debate, anyone?)
    In the end, Lisp macros are Lisp programs executed during compilation and are therefor just as powerful as the language itself. Preprocessor macros are just parametric text replacements.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  7. #7
    Registered User
    Join Date
    Apr 2003
    Posts
    2,662
    Wow. Nice post. <retreats out of the forum backwards, repeatedly bowing low to the ground>

  8. #8
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,893
    Oh, please. Don't be ridiculous.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  9. #9
    Registered User
    Join Date
    Aug 2006
    Posts
    14
    Wow. Nice post. <retreats out of the forum backwards, repeatedly bowing low to the ground>
    I agree. Thanks for the answers!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 72
    Last Post: 01-26-2009, 12:03 PM
  2. My C89 RANT!
    By evildave in forum C Programming
    Replies: 12
    Last Post: 12-07-2005, 09:15 PM
  3. im extreamly new help
    By rigo305 in forum C++ Programming
    Replies: 27
    Last Post: 04-23-2004, 11:22 PM
  4. Prime Number Generator... Help !?!!
    By Halo in forum C++ Programming
    Replies: 9
    Last Post: 10-20-2003, 07:26 PM
  5. include question
    By Wanted420 in forum C++ Programming
    Replies: 8
    Last Post: 10-17-2003, 03:49 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21