How properly inherit from template?

This is a discussion on How properly inherit from template? within the C++ Programming forums, part of the General Programming Boards category; And if string changes, to_upper must change. Nonsense. Patently false. I've written entire generations of source for implementing a wide ...

  1. #91
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    4,178
    And if string changes, to_upper must change.
    Nonsense. Patently false. I've written entire generations of source for implementing a wide variety of mechanics for a large number of objects distributed by third parties.

    Let us say, for example, you offer an implementation of string 'ustring' that provides only these methods: 'char at(unsigned long) const', 'unsigned long size() const', void set(unsigned long, char)', 'void resize(unsigned long)'.

    With those four functions, and no others, my library, without modification, provides a wide variety of sorting, searching, serialization, and dozens of other transformations. I would have to implement exactly nine manipulators, six getters and three setters, accounting for at most a few dozen lines of code. If the public interface changes, still providing at least the abilities those four functions provide, I would only have to change those nine manipulators. The rest of the library, some 218,000 lines, would remain untouched.

    (The trick for those who have played with generic programming: the nine manipulators provide an abstraction for iterators/accessors/etc. Nowhere in the code is, for example, 'some_type::begin()' or 'some_type:perator []' ever used.)

    Coupling, in the programming world, has nothing to do with the requirement that some interface must eventually be available. Or do you honestly claim that source using a public interface on three thousand separate occasions is no less coupled than source using a public interface on exactly one occasion?

    Please. Spare me the latest Silver Bullet hype. Generic programming is just another tool in the toolbox.
    Precisely, but I wonder, what exactly is your point? It is after all a tool? Are you saying we shouldn't use it?

    Soma

  2. #92
    Registered User
    Join Date
    Apr 2008
    Posts
    890
    Quote Originally Posted by phantomotap View Post
    Precisely, but I wonder, what exactly is your point? It is after all a tool? Are you saying we shouldn't use it?
    Not at all. I'm saying to spare me the pulpit speeches about a "new revolution" and that a bunch of blind sheep are somehow "missing the boat".
    Last edited by medievalelks; 04-24-2008 at 12:19 PM.

  3. #93
    Registered User
    Join Date
    Apr 2008
    Posts
    890
    Quote Originally Posted by phantomotap View Post
    Coupling, in the programming world, has nothing to do with the requirement that some interface must eventually be available.
    In fact, that is a form of coupling.

    Or do you honestly claim that source using a public interface on three thousand separate occasions is no less coupled than source using a public interface on exactly one occasion?
    No, that's not what I have claimed and is orthogonal to what we were discussing.

  4. #94
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,452
    OK, first of all... A lot of you see to be going on how free functions increase encapsulation. I don't disagree. Free functions can be ore flexible.
    I don't like free functions, however. I like member functions before, if possible. In my opinion.

    Quote Originally Posted by laserlight View Post
    The argument that member functions are tightly coupled to the class whereas free functions that are not friends reduce coupling is not mere opinion based on personal taste, but one seen to be true by observation. One can reason that tight coupling gives less flexibility to changing the interface, which in turn means more difficult maintenance and extension.

    I think I have cited some of the literature to you :|
    You have. I can bust one thing, however.
    Free to_upper won't need to change as long as the public interface does not change. But that means we can make a member function that uses common interfaces that do not change or use the public interfaces to get the data. Not the most efficient, but it works just the same as the free function.

    As for the other... well, free functions can still be better.
    But even if there was just as member function that called the free function, I'd be happy. Solution for both worlds.

    Quote Originally Posted by phantomotap View Post
    This is nonsense. I've never said that objects should be bare. All objects will naturally have behaviors that only the objects will be capable of performing correctly. All objects will naturally have state that only the objects will be capable of manipulating correctly. This, however, is not what you are arguing. You are arguing for far more than this. Quite simply: do you know better how to sing "Music of the Night" than a cat?
    I am saying that an object's member function should always know how to perform some task better than a free function. If the free function is better, then there's something wrong with your implementation of the member function.

    Lumping behavior and state with an object simply because you find the source more appealing is just plain wrong.

    Lumping behavior and state with an object because you want intellisense to do your job is just plain wrong. (Nothing wrong with using tools to make your job easier, but if the tools are the deciding factor in the design you need to get better tools.)
    As I mentioned above, member functions can still work fine if you change the interface. Nothing different here with those and free functions. Free functions are good for other things, especially algorithms.
    And it's not about intellisense. In this case, intellisense simply makes easier even easier.

    Nonsense. With a freestanding function I can absolutely depend on the mechanism being implementable with an appropriate named, stable interface regardless of the container source. (Yes, you may have to decorate the name, and the function may require the use of a method, but the decorated name will be stable.) With the method version I have to rely on the programmer to provide the exact method. If one doesn't provide the exact method I must re-implement the target source. If the programmer changes the method interface I must upgrade the target source. However, with just a little extra forethought the freestanding function has insulated me from changes. I have increased encapsulation. (As... someone said, LL?!, "less typing" is a pointless metric. Just in case there is an example.)
    To this I simply respond the same as above. This isn't about less typing, but that the object should do it, not someone else.

    It seems to me his problems with algorithms is, their greatest feature, that they are too generic. (And as you said, he is lumping many issues together.) His only arguments favoring methods over "std::algorithms" seem to be that they are difficult to use correctly. Naturally of course, a "one trick pony" will be easier to use correctly and something as generic as 'std::transform' will be more difficult even if it is presented as a member function.

    Anyway, using 'std::transform' is fine for transforming a string to lower case. The trick is not using 'char'/'wchar_t' based strings and the C inherited 'std::tolower' as the transformation function.
    Yes, they are more error prone, harder to read and the object isn't doing the work, someone else is.
    That's all.
    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.

  5. #95
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,450
    Free to_upper won't need to change as long as the public interface does not change. But that means we can make a member function that uses common interfaces that do not change or use the public interfaces to get the data. Not the most efficient, but it works just the same as the free function.
    That's true, as long as the extra member functions do not use anything non-public they will have the same advantage in loose coupling as non-member non-friend functions. Likewise, you can always make all the members public, and as long as no one breaks the documented rules, everything will be fine and dandy (and it can be somewhat fine and dandy, e.g., in C or PHP 4).
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  6. #96
    Registered User whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    7,638
    I don't like free functions, however. I like member functions before, if possible. In my opinion.
    If you don't mind, I'd like to try to appeal to your sense on this matter. It's fine that you have an opinion, but people are obviously getting confused, trying to pin you down to a hard line statement. It's hard to argue with a guy that goes, "Well, maybe free functions can be sort of useful but if possible in my opinion we should use member functions, maybe if everybody's okay with that. Please."

    So maybe, we'll be enlightened within the next few posts.
    I am saying that an object's member function should always know how to perform some task better than a free function. If the free function is better, then there's something wrong with your implementation of the member function.
    Are you suggesting that a generic algorithm is never suited to a task? At face value, this statement can be too absurd. For example, what if you had a list of some objects, and you had to copy the list into a better data structure for other processing (such as searching), like a tree?

    Isn't it a better approach not to assume what data structure works best for your object? It seems like if you take this behavior to the extreme it would become tedious to make something useful. Since <list> and <map> aren't built to morph into one another I can't use a member, and it makes even less sense to hack this behavior into the data.

    You state that you prefer a logical breakdown:
    methods -> free functions -> generic algorithms

    How aggressive are you in persuing your best approach? Are you rebuilding the STL with algorithms as classes? Seriously, like:

    binary_search< item, value > test( ).go( );

    Would you recommend this? Perhaps I'm just a bit comfortable with what I know but I don't see the same glaring error that you do, exactly. I point out that foo.bar() is essentially the same as bar( foo ); the difference is in syntactic sugars. bar is not necessarily a free function, at least, if you've ever used python. I don't think there is a valid argument there and if we are to assume that your whole critiscism of the STL is based on syntactic sugar, than you're a silly goose. Programming is much more than syntax.

    I wonder if I hit the proverbial nail on its' head. It's really hard for me to figure out why everybody is carrying on.

  7. #97
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    4,178
    In fact, that is a form of coupling.
    Nope. Not in the programming world. I can freely create a binary, say a DLL, requiring an interface that may never exist. I can freely create a template that requires an interface that may never exist. This isn't coupling or lack of coupling to my mind, but something else entirely. (I might should mention that this was in response to your repeated "but the interface must be available" in response to "package distribution".)

    No, that's not what I have claimed and is orthogonal to what we were discussing.
    Coupling in the nature of C++ programming is basically all I have been discussing for some time. I have no idea what you are discussing, but you should perhaps stop responding to me if you aren't discussing this topic. (Or, alternatively, you might do more to explain what you are discussing and who you think you are discussing it with.)

    Free to_upper won't need to change as long as the public interface does not change. But that means we can make a member function that uses common interfaces that do not change or use the public interfaces to get the data.
    Nonsense. You can say a 'to_upper' method won't need to be changed. That isn't the point of making and using freestanding functions over methods. One goal is to insulate yourself from changes. That changes may not occur is irrelevant; what if change happens? (Obviously, a no parameter 'to_upper' would likely never change in interface. Changes in a mechanic however...)

    I am saying that an object's member function should always know how to perform some task better than a free function. If the free function is better, then there's something wrong with your implementation of the member function.
    Nonsense. If there exists a correct, complete implementation for some mechanic then the public method and freestanding function must be same--or one is lacking in correctness or completeness. If the freestanding function, complete and correct as above, can exist then the only thing you might possibly gain compared with a method is typing a few less characters.

    With your logic, you must inherit from 'cat' to introduce a new type 'cat_what_can_sing'. Now, obviously, again with your logic, 'cat_what_can_sing' can't just provide an additional interface for implementing freestanding 'sing_song' functions; instead, you must introduce yet another typed named 'cat_what_can_sing_music_of_the_night' providing the method 'sing_music_of_the_night' that 'cat_what_can_sing::sing' might call. All I can say is: Gods help you if you want the thing to sing more than one song. >_<

    As I mentioned above, member functions can still work fine if you change the interface. Nothing different here with those and free functions. Free functions are good for other things, especially algorithms.
    False. I have no idea why you responded with this. As has been said, if, for whatever reason, you decide to change the interface of your method, I must change the target source. I can keep the target source unchanged if I write it with a freestanding function to begin with precisely because I can control the freestanding function. They are obviously very different.

    To this I simply respond the same as above.
    In which case, you didn't address anything, at all, in the quote associated with this response.

    Yes, they are more error prone, harder to read and the object isn't doing the work, someone else is.
    Nonsense. They, that is to say the use, are not more error prone than any alternative. (A large number of "one trick ponies" is not an alternative to a generic function, method or freestanding.) That the object isn't "doing the work" is a tremendously odd statement. (If the method only serves to call other methods or freestanding functions the different is entirely syntactical.) With "harder to read" being subjective entirely.

    Anyway, I have to ask: In my library there are no freestanding functions, only objects--"functiods"--that must be instantiated; who/what "does the work"? I mean, my variant of 'std::copy' creates an instance and invokes my variant of 'std::assign' repeatedly which in turn may call a virtual copy constructor of some object, for example. (A long story involving disheartening tales of caching, exception requirements, threading goals, and the all important interface dreams. My 'std::vector', for example, "behaves" "correctly" for 'std::vector<some_type &>' in the face of threading, exceptions, and manages to be pretty fast all the same.)

    I wonder if I hit the proverbial nail on its' head.
    He has claimed that it isn't just typing and inferred that it isn't syntactical sugar. I wonder...

    Soma
    Last edited by phantomotap; 04-24-2008 at 01:29 PM.

  8. #98
    Registered User
    Join Date
    Apr 2008
    Posts
    890
    Quote Originally Posted by phantomotap View Post
    Nope. Not in the programming world. I can freely create a binary, say a DLL, requiring an interface that may never exist. I can freely create a template that requires an interface that may never exist. This isn't coupling or lack of coupling to my mind, but something else entirely.
    As you say, that is your opinion. I disagree with it.

    Coupling in the nature of C++ programming
    Coupling is an overloaded term and it's obvious we're talking about different kinds.

    I have no idea what you are discussing,
    I was discussing the difference between string::to_upper and to_upper(string), before you changed the subject to the frequency of use of one or the other, and how *that* implies coupling of a sort. Interesting, but hardly what we were discussing.

    but you should perhaps stop responding to me if you aren't discussing this topic.
    Since it's about as easy as nailing jello to the ceiling, I think I'll do just that.

  9. #99
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,452
    Quote Originally Posted by citizen View Post
    Are you suggesting that a generic algorithm is never suited to a task? At face value, this statement can be too absurd. For example, what if you had a list of some objects, and you had to copy the list into a better data structure for other processing (such as searching), like a tree?
    No, no. OK, I'm trying to set things right here.
    Algorithms:
    - Good in sense that they can perform tasks so that you don't need to rewrite code that does the same thing on multiple objects.
    - Error prone in sense that it may require a couple of arguments and they must be right.
    - Lessens readability because an algorithm is not an easy thing to some and especially those who do not know the algorithm or what it does.

    Free functions:
    - Good in sense that they are not limited to one object - they can work with multiple string classes, say, given they have the right interface.
    - Increase encapsulation.
    - More readable than algorithms.
    - Bad in that this is the "the classes themselves does not do the work" analogy (I'll explain that later).

    Member functions:
    - The objects themselves perform the work.
    - Most readable of all three.

    And the "the class does all the work" or not... if you call a free function, then the function is doing the work. If you call a member function, the class does the work.
    It's not about where the code goes or how it works, but about who you are assigning to make it work. The function you're calling. It doesn't matter if the member function to_lower calls the free to_lower--that's implementation issues which are always hidden from the outside.

    I mean, just because you're an expert in some profession doesn't mean you can't hire someone to help. So whatever happens after you call a member function doesn't matter the slightest. The implementation in a class is hidden to the outside - as it should be. We don't know what happens inside nor should we care. That's the class's out business.

    You state that you prefer a logical breakdown:
    methods -> free functions -> generic algorithms

    How aggressive are you in persuing your best approach? Are you rebuilding the STL with algorithms as classes?
    Am I? Yes and no, to an extent. No, I'm not rebuilding any STL classes per se, but I am building a big framework myself. Mostly I've been reorganizing and encapsulating C stuff (like Windows API), but I'm also planning on writing my own string class because the existing ones are lacking.

    Seriously, like:

    binary_search< item, value > test( ).go( );
    I don't know if I would do that. It's constructing the item. That's the work of the constructor, is it not?

    Would you recommend this? Perhaps I'm just a bit comfortable with what I know but I don't see the same glaring error that you do, exactly. I point out that foo.bar() is essentially the same as bar( foo ); the difference is in syntactic sugars. bar is not necessarily a free function, at least, if you've ever used python. I don't think there is a valid argument there and if we are to assume that your whole critiscism of the STL is based on syntactic sugar, than you're a silly goose. Programming is much more than syntax.
    It's not about the syntactical that I'm hung over, but it's more of the idea who does the work. The free function or the class? If it's a class that you're working with, then the class should do the work, if possible. Because we're breaking the concept that a class is an object with free functions. In that I mean, the object should do all the work - you shouldn't tell someone else to tell the object to do it.
    And the object itself can do the things better than a free function because it has access to its private members and internal workings. So the object can always be more efficient, at the cost of some encapsulation.

    Quote Originally Posted by phantomotap View Post
    Nonsense. You can say a 'to_upper' method won't need to be changed. That isn't the point of making and using freestanding functions over methods. One goal is to insulate yourself from changes. That changes may not occur is irrelevant; what if change happens? (Obviously, a no parameter 'to_upper' would likely never change in interface. Changes in a mechanic however...)
    Not nonsense. What the free function does is just take an extra argument and call the public interfaces. I could just as well create a member function that takes no extra arguments and uses public interfaces.
    This completely eliminates the advantage of making it freestanding for this argument.
    However, they are good for other things - especially not requiring to implement the same methods into all classes since a free function can work over multiple classes.
    (But then again, you could just copy the member functions over to the other classes. If they use public interfaces, no changes needs to be made. This is, of course, assuming that the member function and the free function uses the same functions, in which case both would work or both would fail.)

    Nonsense. If there exists a correct, complete implementation for some mechanic then the public method and freestanding function must be same--or one is lacking in correctness or completeness. If the freestanding function, complete and correct as above, can exist then the only thing you might possibly gain compared with a method is typing a few less characters.
    Indeed, but the object would do the work, as it should.

    With your logic, you must inherit from 'cat' to introduce a new type 'cat_what_can_sing'. Now, obviously, again with your logic, 'cat_what_can_sing' can't just provide an additional interface for implementing freestanding 'sing_song' functions; instead, you must introduce yet another typed named 'cat_what_can_sing_music_of_the_night' providing the method 'sing_music_of_the_night' that 'cat_what_can_sing::sing' might call. All I can say is: Gods help you if you want the thing to sing more than one song. >_<
    So sue me. I like it better with objects. Within reasonable limits, I will reinvent the wheel.

    False. I have no idea why you responded with this. As has been said, if, for whatever reason, you decide to change the interface of your method, I must change the target source. I can keep the target source unchanged if I write it with a freestanding function to begin with precisely because I can control the freestanding function. They are obviously very different.
    Untrue. See above.

    Nonsense. They, that is to say the use, are not more error prone than any alternative. (A large number of "one trick ponies" is not an alternative to a generic function, method or freestanding.)
    How is algorithms not error prone? Unless you know how to use them, which is harder than normal member function OR free functions, they WILL go wrong.

    That the object isn't "doing the work" is a tremendously odd statement. (If the method only serves to call other methods or freestanding functions the different is entirely syntactical.) With "harder to read" being subjective entirely.

    Anyway, I have to ask: In my library there are no freestanding functions, only objects--"functiods"--that must be instantiated; who/what "does the work"? I mean, my variant of 'std::copy' creates an instance and invokes my variant of 'std::assign' repeatedly which in turn may call a virtual copy constructor of some object, for example. (A long story involving disheartening tales of caching, exception requirements, threading goals, and the all important interface dreams. My 'std::vector', for example, "behaves" "correctly" for 'std::vector<some_type &>' in the face of threading, exceptions, and manages to be pretty fast all the same.)
    I addressed that above. Have a read.
    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.

  10. #100
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Speaking of coupling, suppose we have a class A and we want to add some functionality that can be implemented in terms of the public interface. Suppose we have two users "first.cpp" and "second.cpp" and only the second user wants to use the new functionality. Which is better, change A and force both users to recompile or add the functionality as a free member in a new header file and recompile only the second user which includes this header?

    I was discussing the difference between string::to_upper and to_upper(string)
    In case of boost::to_upper, it is generic and in no way coupled with std::string. It doesn't accept a std::string, it accepts a WritableRangeT.

    Elysia, when you are saying that it's better if the class does the work, do you really think the best strategy is to put everything that anyone might want to use a class for in the class? Ok, lets say I want vector::random_shuffle and deque::random_shuffle. Then I might also want vector::increment_by_one and list::erase_every_second_item. Etc. Does it not seem that at some point you'd have to say no, because the required functionality is too specific and the user should implement it themselves. A class simply cannot cater for all conceivable needs.

    So, what you can only argue about is that the C++ standard libraries say no too early.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  11. #101
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,452
    Quote Originally Posted by anon View Post
    Elysia, when you are saying that it's better if the class does the work, do you really think the best strategy is to put everything that anyone might want to use a class for in the class? Ok, lets say I want vector::random_shuffle and deque::random_shuffle. Then I might also want vector::increment_by_one and list::erase_every_second_item. Etc. Does it not seem that at some point you'd have to say no, because the required functionality is too specific and the user should implement it themselves. A class simply cannot cater for all conceivable needs.

    So, what you can only argue about is that the C++ standard libraries say no too early.
    Indeed, I must agree to some point. But I should also agree that if such is the case you should not lock it down. Instead, you should make it open to be derived so users can add more functionality if they require it.
    But some things like to_lower, to_upper I really think they could have added for free.

    But as to your ponder, I'd say add it as a member. Even if it means recompiling, it means you don't have to litter free functions everywhere in new headers everytime you want to change the interface or add new functionality.
    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.

  12. #102
    Registered User whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    7,638
    Quote Originally Posted by Elysia View Post
    Free functions:
    - Good in sense that they are not limited to one object - they can work with multiple string classes, say, given they have the right interface.
    - Increase encapsulation.
    - More readable than algorithms.
    - Bad in that this is the "the classes themselves does not do the work" analogy (I'll explain that later).

    Member functions:
    - The objects themselves perform the work.
    - Most readable of all three.

    And the "the class does all the work" or not... if you call a free function, then the function is doing the work. If you call a member function, the class does the work.
    Algorithms are abstract since they detail a process, so I don't think that there are valid criticisms beyond what the algorithm does and how it performs. Any attempt to use an algorithm needs an implementation, where your opinions about methods and functions would be applicable. Despite what you may say there are "simpler" implementations of these aside from the choices made in C++, though far be it from me to assume your opinion.

    I need to cite what you said to someone else to make a point:

    Not nonsense. What the free function does is just take an extra argument and call the public interfaces. I could just as well create a member function that takes no extra arguments and uses public interfaces.
    This completely eliminates the advantage of making it freestanding for this argument.
    However, they are good for other things - especially not requiring to implement the same methods into all classes since a free function can work over multiple classes.
    By your own admission, the only thing that a free function would do is call upon your interface, and there is no difference between that and the dot operator, essentially. You are making a syntactic argument, by preferring methods and presuming there is some pressing reason to hide the public interface. If your interface isn't helping the class "do its own work" in the sense that it could use itself, then it seems like your public methods have a design problem. The interface is how the object "does its own work."

    We're going to have trouble buying your argument if it is only valid when you create a design problem in some object. If method complex() can only be used by method simple(), than simple() should be in the interface and not complex(). complex() is not a reason to avoid the rest of the program. Hide complex() within the recesses of the class, call it when you are supposed to through the interface. Presumably, this would allow safe free functions to be made, regardless of your opinion about whether a member function looks better.

    Teamwork is important if you are going to write a program for anyone with the help of others.
    Last edited by whiteflags; 04-24-2008 at 03:19 PM.

  13. #103
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Quote Originally Posted by Elysia View Post
    Indeed, I must agree to some point. But I should also agree that if such is the case you should not lock it down. Instead, you should make it open to be derived so users can add more functionality if they require it.
    But some things like to_lower, to_upper I really think they could have added for free.

    But as to your ponder, I'd say add it as a member. Even if it means recompiling, it means you don't have to litter free functions everywhere in new headers everytime you want to change the interface or add new functionality.
    I wouldn't mind to_upper and to_lower as part of the standard as well, but I really don't mind them as free functions (as in boost: they are just as simple to use but are more generic).

    As to the second point. What if the new functionality was really specific and only needed by one file and not needed by 100 files? What if it was more than one (related but specific) function and I want to recompile the project often? So the choice is between separating the really specific things in a separate header or littering the class forever with things I might never need again?
    Last edited by anon; 04-24-2008 at 03:34 PM.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  14. #104
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,452
    That's a difficult one to answer. I'd like everything neatly into place, but... if it adds too much compile time I'd absolutely find another way of doing 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.

  15. #105
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    4,178
    I was discussing the difference between string::to_upper and to_upper(string), before you changed the subject to the frequency of use of one or the other, and how *that* implies coupling of a sort. Interesting, but hardly what we were discussing.
    Oh, well, if you were discussing the merits of one versus the other in terms of coupling and still said what you have said, then we weren't discussing different kinds of coupling; your just wrong in understanding what coupling is and the levels with which things can be coupled. (See, primarily, "And if string changes, to_upper must change.", but really everything you said on page 6 of this thread.)

    I can't implement 'string::to_upper()', but I can implement 'string to_upper(string)'. This alone says that 'string to_upper(string)' isn't as tightly coupled to 'string' as 'string::to_upper()'.

    I can couple my implementation of 'string to_upper(string)' to 'string' tightly in interface and mechanic by using 'string::to_upper()'. Granted, in the examination of only this function and this method, this would be pretty pointless and is obviously very tightly coupled.

    I can couple my implementation of 'string to_upper(string)' to 'string' tightly in interface only by relying on details of the implementation of the interface of 'string'. (That is, not using 'string::to_upper()' directly.) If the mechanic of 'string::to_upper()' changes, possibly using a different metric in transforming Latin characters for example, my 'string to_upper(string)' will keep the same mechanic, but the source of 'string to_upper(string)' may need to be updated to reflect any changes.

    I can couple my implementation of 'string to_upper(string)' to 'string' loosely by using something very like the iterator pattern if it supports it. Changes in the details of of the 'string' implementation no longer affect me. still though, if changes are made to the iterator interface provided by 'string' the source of 'string to_upper(string)' would have to be updated.

    I can couple my implementation of 'my_string_interface to_upper(my_string_interface)' to 'my_string_interface' loosely using something very like the iterator pattern. Further, I can couple 'my_string_interface' loosely to 'string' using something very like type erasure and the iterator pattern. Changes in the details of any string type 'my_string_interface' supports doesn't concern 'my_string_interface to_upper(my_string_interface)' in any way and the source of 'my_string_interface to_upper(my_string_interface)' need never be changed. (That is, 'my_string_interface to_upper(my_string_interface)' and 'string' are in no way coupled.)

    Finally, I can add a further layer of indirection and "erase" 'my_string_interface' by, for example, passing messages around--requiring 'my_string_interface to_upper(my_string_interface)' to be an object masquerading as a function. Changes in the interface of 'my_string_interface' doesn't concern 'my_string_interface to_upper(my_string_interface)' in any way. The details, the interface and implementation of 'my_string_interface' any string type it supports can be safely ignored. (Messages here is intended to mean free message passing and not the ridiculous notion of parameterless C++ methods as messages.)

    Naturally, because passing references around requires only a class declaration, you could implement a 'string to_upper(string)' in terms of these other functions if slightly modified to 'void to_upper(string &, string &)'. This object-oriented implementations would then require a slight change and a little more typing.

    With templates, you can go in the opposite direction. Tell everything to carry more type information so that the actual type and interface being targeted can safely be ignored because 'string to_upper(string)' will never use them.

    With meta-programming, you can go so far as you like in either direction. This is my preference because every action is abstracted and even the interface employed in writing 'string to_upper(string)' will not actually exist until it is actively used. (This is, almost certainly, what Boost/META/ETC. would choose as well.)

    It's not about the syntactical that I'm hung over, but it's more of the idea who does the work.
    Well, thanks for that. At least now I know your arguing over syntax. If all functions, method and freestanding, had to be called the same, or as if in dotNet you could add "methods" to the class list from outside the class package, then this "do the work" nonsense would not stand. By definition a function does work; if it calls on other functions/methods/etc. they do work. (Though, C++0x is supposed to give us a way for forwarding functions to not, infact, do work.) As it is, in C++, you might show a given example as "doing the work" but only because of the syntax involved, but because this is C++ you are forcing a bad design on your objects because you think that the source is prettier.

    Not nonsense. What the free function does is just take an extra argument and call the public interfaces. I could just as well create a member function that takes no extra arguments and uses public interfaces.
    This completely eliminates the advantage of making it freestanding for this argument.
    Nonsense. Your not addressing the issue, but I must admit you are ignoring it admirably. Because the distributer controls the class one can not rely on the interface being unchanged. Period. You can't argue otherwise. You can't because it has happened. It will happen again. It has happened in dotNet for example. Even examining only a method versus a freestanding function the freestanding function wins if both can do the job with the same sophistication. Ignoring the actual use of one versus another, the interface, again ignoring the mechanic entirely, of the freestanding function may remain unchanged forever because the user of the class can control it. You can't wave away the goal of decoupling by claiming that the interface to a method will remain unchanged. Then, of course, there is the mechanic, the use of one versus the other. The distributes definition of 'to_upper' may change even if the interface doesn't; the programmers definition may stay the same.

    Indeed, but the object would do the work, as it should.
    No it would not. It is syntactical sugar. That is all you are arguing.

    Within reasonable limits, I will reinvent the wheel.
    I have said many times that I have no problem reinventing the wheel for gain. If you like objects better for whatever reason go for it. (I certainly do. I like templates more than non-templates as well.) Still though, cramming the objects full of data and methods that have no business being there is bad design... wheel or no wheel.

    Untrue. See above.
    ^_^

    Unfortunately, that doesn't address the issues either, but at least I know that you are arguing only because you think the syntax is the sexy. Rather reminds me of me.

    How is algorithms not error prone?
    Who said they were not error prone? It certainly wasn't me. The point is, they are not less error prone than any alternative. As I said, a large number of methods or freestanding functions implementing what can be achieved with the STL is not an alternative. (It is a ridiculous and mindless attempt to provide an alternative.) But, let's say for the sake of argument that such is an alternative. Knowing, or finding out, which of thousands of methods to call is going to be error prone in the extreme and/or extremely time consuming. (Remember we are talking the STL--templates that can operate on virtually any metric in other words.)

    Consider for just a moment the real world: which sorting algorithm to use depends on the type of data stored, the number of elements stored, how sorted the data already is, and especially the quality of the comparison functions, and you do not always sort by the same data, and even when you do sort by the same data you may wish to sort that data by a different metric. Off hand, you'll need about three hundred different sorting methods for your string type. (Based on a guess of how many transformation functions I've written.)

    That said, for those of you who have a hard time with the STL, debug versions of the STL have been available for some time that prevents the most common errors at compile-time, logs most other errors at runtime, and allows more creative source for simpler invocation. (I know I wrote some it.) Granted, it is based on STLPort and requires some Boost libraries, but that is hardly the point. There used to be a post on the STLPort form with a distribution.

    I addressed that above. Have a read.
    Didn't. Saying "I like the syntax." isn't addressing the issue. It's ignoring them beautifully, but ignoring them all the same.

    Speaking of coupling, suppose we have a class A and we want to add some functionality that can be implemented in terms of the public interface. Suppose we have two users "first.cpp" and "second.cpp" and only the second user wants to use the new functionality. Which is better, change A and force both users to recompile or add the functionality as a free member in a new header file and recompile only the second user which includes this header?
    A new "free member"? Color me confused... Anyway, I'm thinking this question wasn't meant for me. I just thought that was a little funny.

    Soma

Page 7 of 8 FirstFirst 12345678 LastLast
Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Specialising a member function with a template template parameter
    By the4thamigo_uk in forum C++ Programming
    Replies: 10
    Last Post: 10-12-2007, 04:37 AM
  2. Screwy Linker Error - VC2005
    By Tonto in forum C++ Programming
    Replies: 5
    Last Post: 06-19-2007, 02:39 PM
  3. error: template with C linkage
    By michaels-r in forum C++ Programming
    Replies: 3
    Last Post: 05-17-2006, 08:11 AM
  4. Class Template Trouble
    By pliang in forum C++ Programming
    Replies: 4
    Last Post: 04-21-2005, 04:15 AM
  5. oh me oh my hash maps up the wazoo
    By DarkDays in forum C++ Programming
    Replies: 5
    Last Post: 11-30-2001, 11:54 AM

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