Though implementation problem

This is a discussion on Though implementation problem within the C++ Programming forums, part of the General Programming Boards category; Originally Posted by phantomotap Templates are templates. They aren't special. Sure they are. The compiler refuses to see them as ...

  1. #271
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,536
    Quote Originally Posted by phantomotap View Post
    Templates are templates. They aren't special.
    Sure they are. The compiler refuses to see them as a unspecialized type. Therefore, CTest does not exist, but CTest<int> might (at the point where the code uses a CTest<int> class).

    And thus, the other problem: you can't say that the constructor taking a 'const the_same_type_as_the_first_template_argument *' of 'CTest' actually takes a 'const wchar_t *' because you've not yet assigned those arguments values/types. Without a fully instantiated template you can't determine if the referenced types of the template arguments support any construct.
    But that's just the thing! If the compiler looked inside the class for a proper constructor, it should be able to guess the type of T. If it looked at my const T* constructor, it should be able to guess the type of T = wchar_t, and replace T with wchar_t and seeing as the argument is const wchar_t* and the constructor takes const wchar_t*, the compiler made a good guess that works and thus it have deduced T.
    This is what I was referring to that a compiler could do (but apparently doesn't).

    I have no idea what you mean to be saying. C++ doesn't parse anything upwards.
    In essence that you cannot use a class which hasn't been defined up to the point where you use it (it must be available on a previous line somewhere, thus "upwards".)

    Requiring that a specialization appears before its first use changes nothing about how a compiler might determine which specialization to instantiate.
    Of course it does. Or would. In the ideal compiler.
    Because then the compiler would be able to see all possible outcomes of the class CTest before the instantiation line. Thus it can parse all of those to see if it can find a match to its liking. Omitting them is the same as omitting half the definition of a class. Or would be. A specialization is part of the class CTest, part of the unspecialized class.

    It's simple. You can't examine the values associated with the parameters of a function before it is called; by the same logic, you can't determine the types associated with template parameters until it is instantiated.
    Right, but the idea was that the compiler could guess.

    Nope. It's much simpler than that. The compiler can't create a 'CTest' without an explicit type period. It can't because it is a template by which other types are crafted.
    This is what shouldn't be. The compiler should be able to guess and try to resolve the ambiguity by checking the class and see if it can match a type.
    It shouldn't give up just because the instantiation is unspecialized.

    The compiler can and does search inside a class for conversion functions. That isn't the problem. The compiler doesn't know which class to search.
    There's only one unspecialized class, so search all parts of it

    A generic 'T' matches everything. If I have a partial specialization of 'CTest', before the point of invocation or later in the source, named 'template <typename T> CTest<type_vector<T, T>>' that "always" has a constructor taking 'const wchar_t *' as a parameter how do you determine what value 'T' should have? You can't. The compiler can't, and the compiler doesn't try.
    It can still resolve T to a type and then use the rules for best overloaded function to call. If it can't decide - then it will just return error - ambiguous.

    Your example is logically wrong, but I'll give you the befit of doubt. (That is, I'll assume your going to correct the inconsistencies.) I'll even give you some "source"--like yours--of my own for you to chew over. Actually, I'll give you two different chunks.
    It's not wrong

    Code:
    template <typename T> class CTest {CTest(const T*){} typedef T type;};
    template <typename T> class CTest<type_vector<T, T>> {CTest(const char *){} typedef type_vector<T, T> type;};
    int main()
    {
    CTest test("my test");
    }
    Which template class did I intend to instantiate?
    Which instantiation is more appropriate? Why?
    What would 'type' be a typedef for? And in the other case?
    The compiler would unfold the code to:
    Code:
    template <> class CTest {CTest(const char*){} typedef char* type;};
    template <> class CTest<type_vector<char*, char*>> {CTest(const char *){} typedef type_vector<char*,char*> type;};
    int main()
    {
    CTest test("my test");
    }
    And since there are two templates with the same constructor (one argument, T*), it will complain ambiguous.
    Code:
    template <typename T> class CTest {CTest(){} typedef T type;}; // Note: Constructor
    template <typename T> class CTest<type_vector<T, T>> {CTest(const char *){} typedef type_vector<T, T> type;};
    int main()
    {
    CTest test("my test");
    }
    There is no ambiguity here; what would 'type' be a typedef for?
    Code:
    template <> class CTest {CTest(){} typedef char* type;}; // Note: Constructor
    template <> class CTest<type_vector<char*, char*>> {CTest(const char *){} typedef type_vector<char*, char*> type;};
    int main()
    {
    CTest test("my test");
    }
    Since only the second class matches the number of arguments in the list, it would instantiate the second and thus type = type_vector<char*, char*>.
    At least in the ideal compiler.
    Last edited by Elysia; 05-26-2008 at 08:13 AM.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  2. #272
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,893
    Sure they are.
    No, they aren't. No more than classes are special. But classes and templates are two entirely different things. When you instantiate a class, you get an object. When you instantiate a template, you get a function or class.

    But that's just the thing! If the compiler looked inside the class for a proper constructor, it should be able to guess the type of T.
    While this is correct, it's also very limited. It wouldn't work for classes with more than one template parameter, for example.

    But actually, deducing template parameters from constructors is something that has been proposed for C++09. It was filed under "not ready for C++0x", so while the interest was there, the proposal was simply not refined enough. Specifying this behaviour is complicated. Feel free to read it for yourself:
    http://www.open-std.org/jtc1/sc22/wg...2007/n2332.pdf
    The proposal is simple - but then, it was also rejected as "not ready".

    (This isn't exactly what you want, tough. This deduction would only work when the template is explicitly named.)


    Since only the second class matches the number of arguments in the list, it would instantiate the second and thus type = type_vector<char*, char*>.
    At least in the ideal compiler.
    Whoa, horrible! Why would T be char*? What relationship between T and the const char* parameter of the constructor can you justify?

    Consider just one example of the consequences:
    Code:
    std::vector v(100); // A vector<int> with 100 elements.
    std::vector v(100u); // A vector<unsigned int> with 100 elements.
    Ever heard of the principle of least surprise?
    Last edited by CornedBee; 05-26-2008 at 08:35 AM.
    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

  3. #273
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,536
    Quote Originally Posted by CornedBee View Post
    But actually, deducing template parameters from constructors is something that has been proposed for C++09. It was filed under "not ready for C++0x", so while the interest was there, the proposal was simply not refined enough. Specifying this behaviour is complicated. Feel free to read it for yourself:
    http://www.open-std.org/jtc1/sc22/wg...2007/n2332.pdf
    The proposal is simple - but then, it was also rejected as "not ready".

    (This isn't exactly what you want, tough. This deduction would only work when the template is explicitly named.)
    Bastards. To think they would reject a revolutionary language feature such as this?
    That would no more exotic, hard-to-read and annoying explicit types for template classes where you have a long, complicated type, such as a function pointer.
    I'd embrace that any day. Even if it may not be 100% what I'm after.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  4. #274
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    4,213
    The compiler refuses to see them as a unspecialized type.
    It can't; templates are a declaration that says what, for any given instantiation, may be the interface and implementation.

    But that's just the thing!
    You can't even guess the type correctly and you think you know.

    In essence that you cannot use a class which hasn't been defined up to the point where you use it (it must be available on a previous line somewhere, thus "upwards".)
    Wrong. You can. I do it everyday. You probably do it everyday you program in C++.

    Because then the compiler would be able to see all possible outcomes of the class CTest before the instantiation line. Thus it can parse all of those to see if it can find a match to its liking. Omitting them is the same as omitting half the definition of a class. Or would be. A specialization is part of the class CTest, part of the unspecialized class.
    You know nothing of meta-programming. Any specializations aren't necessarily related by name, parameters, inheritance, interface, functionality, or even instantiation mechanism to the original template class.

    Right, but the idea was that the compiler could guess.
    No. It can't. The compiler has to know or it's beyond useless.

    This is what shouldn't be. The compiler should be able to guess and try to resolve the ambiguity by checking the class and see if it can match a type. It shouldn't give up just because the instantiation is unspecialized.
    That you think the compiler should determine a type by examination of an unrelated type makes all of your opinions invalid.

    There's only one unspecialized class, so search all parts of it
    Wrong. There are potentially infinitely many unspecialized classes of any given template class.

    It can still resolve T to a type and then use the rules for best overloaded function to call. If it can't decide - then it will just return error - ambiguous.
    The compiler knows it can't determine the templates arguments in such a way.

    It's not wrong
    It is wrong.


    Code:
    template<typename T> class CTest { CTest(const T*) {} };
    int main()
    {
    CTest test("my test");
    }
    it can translate T = char*
    the constructor becomes: CTest(const char*)


    If 'T' became 'char *' the constructor would take a 'const char **'.

    And since there are two templates with the same constructor (one argument, T*), it will complain ambiguous.
    You didn't answer the last question.

    Since only the second class matches the number of arguments in the list, it would instantiate the second and thus type = type_vector<char*, char*>.
    You answered incorrectly. The parameter is not 'const T *'. The parameter is 'const char *'. The type from the template parameter list named 'T' is referenced only in the 'typedef' of 'type'. The template parameters can't be determined even by examining the template class 'CTest' in a typeless way as you apparently wish compilers did. That you tried to answer is sufficiently wrong.

    At least in the ideal compiler.
    Then this "ideal" compiler couldn't compile any template code correctly.

    Soma

  5. #275
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,536
    I can't even begin to phantom how a real C++ compilers works, but I can idealize how an ideal compiler would compile the code.

    Quote Originally Posted by phantomotap View Post
    Wrong. You can. I do it everyday. You probably do it everyday you program in C++.
    Oh really?
    A.h:
    Code:
    class CTest { public: CTest(); };
    A.cpp:
    Code:
    CTest::CTest() { }
    B.cpp:
    Code:
    int main()
    {
        CTest test; // ERROR: Undeclared
    }
    C.cpp:
    Code:
    #include "A.h"
    int main()
    {
        CTest test; // OK
    }
    If B.cpp works, as you say it does, then you've just broken the entire C++ language.

    If 'T' became 'char *' the constructor would take a 'const char **'.
    My typo. I meant T = char.

    You didn't answer the last question.
    Very well... if the compiler instantiates the first class, if it deems it possible, then type = char, since
    typedef T type;

    The ideal compiler would compile all the templates including my ideas of how templates would work.
    Templates are IMHO, far too complex for their own good.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  6. #276
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    4,213
    I can't even begin to phantom how a real C++ compilers works, but I can idealize how an ideal compiler would compile the code.
    I can't tell if that was a joke at my expense or just a mistake. Either way, I loved it.

    Oh really?
    Yes. Have you never written nested classes?

    The ideal compiler would compile all the templates including my ideas of how templates would work.
    Yes, well, mutual exclusion and all that.

    Templates are IMHO, far too complex for their own good.
    Functions are easy. The observer pattern is easy. The "functiod" object is easy. The "tail recursion" concept is easy. It is virtually impossible to understand another programmers implementation of a state machine implemented with these features. Templates are easy. What can be done with templates is another matter.

    You've had what? A month experience with templates? Two months? Despite what the titles suggest, you can't really learn a programming language in 12 hours, 24 hours, 3 days, 7 days, 21 days, or even 1 year. Oh, but you can learn the syntax; syntax is easy. ^_^

    Soma

  7. #277
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,536
    Quote Originally Posted by phantomotap View Post
    I can't tell if that was a joke at my expense or just a mistake. Either way, I loved it.
    Yes, it's truth.

    Yes. Have you never written nested classes?
    I have and I do tend to do that. But they have a nasty comeback bite too since I'm unaware of any way to foward-declare any nested classes.
    I do tend to nest classes, structs and types if I feel they only belong to the class and nothing else.
    (Although I chose not to do that with the string class because of the template headaches it would cause. Heck, it's even a headache even now. When the compiler complains about something, it's often a real headache to figure out why, partly due to the complexity and partly due to the poor error information from the compiler.)

    You've had what? A month experience with templates? Two months? Despite what the titles suggest, you can't really learn a programming language in 12 hours, 24 hours, 3 days, 7 days, 21 days, or even 1 year. Oh, but you can learn the syntax; syntax is easy. ^_^
    Oh sure, I've had several years of experience with templates, but I haven't done any "meta programming," like I've done recently. It's quite recent and the new addition to my arsenal.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  8. #278
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,536
    Well, is there a way to make this work?

    Code:
    template<typename T> class CTest 
    {
    public: 
    	typedef CTest<T> me_t;
    	CTest() {}
    	CTest(const T*) {}
    	CTest(const T) {}
    	template<typename NewT> void operator += (const typename CTest<NewT>::me_t&) {}
    };
    
    void Help()
    {
    	CTest<wchar_t> a;
    	a += L'a';
    }
    The idea is because the operators (for class<X>) takes a class<Y> as argument, which then would wrap type Y inside a class<Y> container by implicit conversion.
    I'm trying to make the following work:

    Code:
    	CInt<uint8_t> i;
    	i += 10;
    While CInt has operators such as:
    Code:
     template<typename NewT> CInt& operator += (const CInt<NewT>& Data) {}
    And constructors such as:
    Code:
    	CInt() {}
    	template<typename NewT> CInt(CInt<NewT> Int) {}
    	template<typename NewT> CInt(NewT Int) {}
    Again, it seems obvious to me that it should work, but it doesn't.
    (The following does not want to work)
    Code:
    private: typedef CInt<T, bUnderflow, bOverflow, bLogging> me_t;
    template<typename NewT> CInt& operator += (const typename CInt<NewT>::me_t& Data) {}
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  9. #279
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,893
    Well, is there a way to make this work?
    Which this? The first, with CTest? Or the second, with CInt? Your description differs significantly from the example code.

    As a general rule, the me_t trick prevents argument deduction. Thus, there's no chance the CTest::+= can work. It's a member template, but there's no way for the compiler to know its template argument.
    But then, I don't see why += should be a template. If it's not a template, but just a simple member, there should be no problem.
    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

  10. #280
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,536
    Quote Originally Posted by CornedBee View Post
    Which this? The first, with CTest? Or the second, with CInt? Your description differs significantly from the example code.
    CTest is the smallest, simplest way of reproducing the problem.
    The real work lies in CInt.

    As a general rule, the me_t trick prevents argument deduction. Thus, there's no chance the CTest::+= can work. It's a member template, but there's no way for the compiler to know its template argument.
    You're right that it doesn't work, but it will not work without me_t either, which is why I tested it in the first place.

    But then, I don't see why += should be a template. If it's not a template, but just a simple member, there should be no problem.
    It can't be mere member, because:
    If the object is say, CInt<int>, then it must be able to accept CInt<long>, as well as any other numeric types of CInt. That's why it's a template member function.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  11. #281
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,893
    If the object is say, CInt<int>, then it must be able to accept CInt<long>, as well as any other numeric types of CInt. That's why it's a template member function.
    Assume that the basic CInt looks like this:
    Code:
    template <typename T>
    class CInt
    {
    public:
      CInt(T t);
      CInt & operator +=(const CInt &rhs);
    };
    And you use it like this:
    Code:
    CInt<long> cil(0);
    int i = 100;
    cil += i;
    This works. Here's why:

    cil += i;
    Here the compiler does two name lookup sequences. It searches the type of the left-hand argument for a member +=, and it searches for global += operators. Specifically, it will search the nesting chain (the current namespace, its outer namespace, and so on until your reach the global namespace - including any imports in those namespaces), and it will search the namespaces of the arguments. (i is an int, so no namespace there. If CInt is in namespace Util, then it will search the namespace Util.)

    It ends up with a list of candidates. The candidate list might look like this:
    CInt<long>::operator +=(const CInt<long> &)
    [built-in] ::operator +=(fundamental&, fundamental)
    Util::operator +=(Unrelated &, const Unrelated &)

    Now it kicks out all operators that do not apply.
    1) There is no conversion from [lvalue]CInt<long> to fundamental&. The built-in += is out. (Give CInt an operator T&, though, and you get ambiguity.)
    2) There is no conversion from [lvalue]CInt<long> to Unrelated&. The Util:: += is out.

    The last remaining is the member operator. It is applicable:
    [lvalue]CInt<long> can be used as the this argument.
    There is a valid conversion chain from [lvalue]int to const CInt<long>.

    A valid conversion ...
    The standard says that a valid conversion is:
    Any number of built-in conversions (see chapter 4 of the standard), then
    Zero or one user-defined implicit conversions (conversion constructors and conversion operators), then
    Any number of built-in conversions again.

    The compiler finds the chain
    [lvalue]int --{built-in: lvalue-to-rvalue}--> [rvalue]int --{built-in: integer promotion}--> [rvalue]long --{user-defined: constructor CInt<long>(long)}--> [rvalue]CInt<long> --{built-in: bind rvalue to const reference}--> const CInt<long>&

    It thus has a valid and unambiguous function to call.
    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

  12. #282
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,536
    Sure it does, but try this:
    Code:
    	CInt<uint8_t> i;
    	i += -1;
    	i += 0xFFFFFFFFFFFFFFFF;
    Yes, the code compiles, but it is far from correct.
    In the first case, -1 is converted to unsigned and 255 is added.
    In the second case, the number is truncated and 255 is added.

    With constructors and operators:
    Code:
    	CInt() {}
    	template<typename NewT> CInt(CInt<NewT> Int): m_Data(Int.m_Data) {}
    	CInt(T Int): m_Data(Int) {}
    	/*template<typename NewT> */CInt& operator += (const CInt& Data) { return *this; } //(const typename CInt<NewT>::me_t& Data) {}
    So my question becomes: what to do to make it right.
    I'm trying to rely on implicit conversions for integer -> CInt<integer>, so the operators can accept and process it.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  13. #283
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    4,213
    I'm trying to rely on implicit conversions for integer -> CInt<integer>, so the operators can accept and process it.
    No. You are not. We've rather "just" discussed the issue. You just want to rely on existing constructs to code additional behavior. (Specifically, you want to rely on constructors and an existing well designed '+=' so that you don't have to code matching '+=' for every constructor.)

    *shrug*

    You really should just bite the bullet and do it properly.

    Anyway, as with virtually every software problem: impose an additional level of abstraction. I've included one possibility. In all honesty, this isn't the "correct" way to approach this particular abstraction, but it is the simplest. (Even the "correct" way is only a construct to allow a generic implementation while maintaining the possibility of outside influences coding more efficient implementations of any given 'operator @'. If your worth the effort of the help you've received, you'll eventually still do it properly maintaining this abstraction only for the possibility of outside influence.)

    Let's see... the important bit: without employing firewall constructs controlling what types you instantiate will be impossible, and without a firewall referencing a specific error every compiler will garbage at you about syntactic impossibilities. Long<->Short: Obtain a good source level firewall and use it.

    Soma

    Code:
    template<typename T> class CTest 
    {
    public: 
    	typedef CTest<T> me_t;
    	CTest() {}
    	CTest(const T*) {}
    	CTest(const T) {}
    	template<typename NewT> void operator__addition(const CTest<NewT> &) const
    	{
    	}
    };
    
    // struct TLERROR_CTest_No_Instantiation_For_Non_Numeric_Type{};
    template<typename OldT, typename NewT> void operator + (const CTest<OldT> & lhs_f, const NewT & rhs_f)
    {
      //raise_error<is_numeric<NewT>, TLERROR_CTest_No_Instantiation_For_Non_Numeric_Type> firewall_01;
      CTest<NewT> temp(rhs_f);
      lhs_f.operator__addition(temp);
    }
    
    template<typename OldT, typename NewT> void operator + (const NewT & lhs_f, const CTest<OldT> & rhs_f)
    {
      //raise_error<is_numeric<NewT>, TLERROR_CTest_No_Instantiation_For_Non_Numeric_Type> firewall_01;
      CTest<NewT> temp(lhs_f);
      temp.operator__addition(rhs_f);
    }
    
    void Help()
    {
    	CTest<wchar_t> a;
    	a + L'a';
    	L'a' + a;
    }

  14. #284
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,536
    Quote Originally Posted by phantomotap View Post
    No. You are not. We've rather "just" discussed the issue. You just want to rely on existing constructs to code additional behavior. (Specifically, you want to rely on constructors and an existing well designed '+=' so that you don't have to code matching '+=' for every constructor.)
    Yes, well, however you want to put it.
    We've "just" discussed it and I do believe I know why it won't work, but I'm still rather new to metaprogramming and do not fully understand how to use such an approach to solve the problem.
    Metaprogramming is a very powerful concept of C++.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  15. #285
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    4,213
    We've "just" discussed it and I do believe I know why it won't work, but I'm still rather new to metaprogramming and do not fully understand how to use such an approach to solve the problem.
    That's absolutely contrary to what I was saying. Do not use templates as a way of subverting the quality conventions of C++. It can be done. It is wrong. One might employee meta-programming to facilitate such effect. It is still wrong.

    If you were designing a "big integer" class, without using templates, you might manage the conversion constructors to simplify the interface and implementation for all the operators. It would be wrong. The operators could perform better if the code for them was written specifically for that purpose. This is true for virtually every class. For classes where this isn't the case there is still benefit from doing things properly. If you setup the interface correctly with operators and explicit constructors many corner cases may safely be ignored.

    Consider your case: if you had gone for a proper, complete interface you would have never noticed that the conversion constructor of a template instance can't be used as a way of determining the arguments to the template itself. The code would have compiled beautifully for all relevant associations.

    The point is: templates are just strongly typed ways of describing classes of interfaces and implementations. Without the polish on the prose, meta-programming may be looked at as a mechanism for generating the templates themselves. The interface and implementation must still be sound even if that means duplication.

    Soma

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. WS_POPUP, continuation of old problem
    By blurrymadness in forum Windows Programming
    Replies: 1
    Last Post: 04-20-2007, 06:54 PM
  2. Laptop Problem
    By Boomba in forum Tech Board
    Replies: 1
    Last Post: 03-07-2006, 05:24 PM
  3. implementation file
    By bejiz in forum C++ Programming
    Replies: 5
    Last Post: 11-28-2005, 12:59 AM
  4. Replies: 5
    Last Post: 11-07-2005, 10:34 PM
  5. Memory Problem - I think...
    By Unregistered in forum C Programming
    Replies: 4
    Last Post: 10-24-2001, 12:14 PM

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