Click here to Skip to main content

Nemanja Trifunovic - Professional Profile

Summary

18,445
Author
7,575
Authority
30,608
Debator
25
Editor
90
Enquirer
9,708
Organiser
5,125
Participant
Born in Kragujevac, Serbia. Now lives in Boston area with his wife and daughters.
 
Wrote his first program at the age of 13 on a Sinclair Spectrum, became a professional software developer after he graduated.
 
Very passionate about programming and software development in general.
Member since Tuesday, June 12, 2001 (11 years, 11 months)
  • 24 Aug 2009: Best C++/MFC article of July 2009
  • 24 Feb 2007: Best C++/MFC article of Jan 2007

Contributions

Articles 15 (Legend)
Tech Blogs 0
Messages 6,093 (Master)
Q&A Questions 0
Q&A Answers 50
Tips/Tricks 0
Comments 19

Links

Reputation

For more information on Reputation please see the FAQ.

Privileges

Members need to achieve at least one of the given member levels in the given reputation categories in order to perform a given action. For example, to store personal files in your account area you will need to achieve Platinum level in either the Author or Authority category. The "If Owner" column means that owners of an item automatically have the privilege, and the given member types also gain the privilege regardless of their reputation level.

ActionAuthorAuthorityDebatorEditorEnquirerOrganiserParticipantIf OwnerMember Types
Have no restrictions on voting frequencysilversilversilversilverAdmin
Store personal files in your account areaplatinumplatinumSitebuilder, Subeditor, Supporter, Editor, Staff
Have live hyperlinks in your biographybronzebronzebronzebronzebronzebronzesilverSubeditor, Protector, Editor, Staff, Admin
Edit a Question in Q&AsilversilversilversilverYesSubeditor, Protector, Editor, Admin
Edit an Answer in Q&AsilversilversilversilverYesSubeditor, Protector, Editor, Admin
Delete a Question in Q&AYesSubeditor, Protector, Editor, Admin
Delete an Answer in Q&AYesSubeditor, Protector, Editor, Admin
Report an Articlesilversilversilversilver
Approve/Disapprove a pending ArticlegoldgoldgoldgoldSubeditor, Mentor, Protector, Editor, Staff, Admin
Edit other members' articlesSubeditor, Protector, Editor, Admin
Create an article without requiring moderationplatinumSubeditor, Mentor, Protector, Editor, Staff, Admin
Report a forum messagesilversilverbronzeProtector, Editor, Admin
Create a new tagsilversilversilversilverAdmin
Modify a tagsilversilversilversilverAdmin

Actions with a green tick can be performed by this member.


 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   


Advertise | Privacy | Mobile
Web02 | 2.6.130516.1 | Last Updated 18 May 2013
Copyright © CodeProject, 1999-2013
All Rights Reserved. Terms of Use
Layout: fixed | fluid

You must Sign In to use this message board.
Search this forum  
GeneralForofobia Pin
Friday, August 20, 2004 2:54 AM by Nemanja Trifunovic
I rarely take part in Soapbox forum discussions, and generally find them boring. However, this rant was really great - a sort of Declaration of Independence from STL - style programming:
 
Forofobia[^]
 
Peterchen[^] seems to be pretty angry with the trend in modern C++ to replace loops with STL-like algorithms. He says, among other things:
 

Look the framework we have to build to minimise (not remove, just "minimise") writing loops:
 
iterators. const. unidirectional. bidirectional. reverse iterators. const or not. iterator adaptor. functors. binders. composers. bind. function. lambda library. anything I forgot? most likely. We need to templatize like hell, bending the compiler to a point where we are happy it makes it through our code alive - and when not, we don't dare ask for sensible error messages. To avoid what?
 
...
 
It's a loop, for god's sake. It's not a bear trap, it's not the infamous goto-spaghetti mess, it's not a terrorist nuke we have to keep out of our code whatever sacrifice of sanity is necessary.
 
What can go wrong in a loop?
- you forget to increment
- you are off by one
- you invalidate the container or the iterator
 
The first requires some discipline, the second some basic calculus training, and the third heaven forbid thinking! whoo!
 
...
 
Resolution: From now on I'll call all algorithm aficionados loopophobics. Yes, Scott Myers, this includes you.

 
Some of the comments from the fellow programmers:
 
after a certain point, trying to turn C++ into Haskell just creates confusion for anyone unfortunate enough to have to maintain the code.
...
 
for loops are way too readable, the whole purpose of STL and especially Boost is to enable the production of completely unreadable code that will utterly confuse the slack-jawed imbecile who only knows C# and is asked to maintain my C++ code.
...
 
This seems to be complexity for complexity's sake, or possibly just to distance itself from anything obvious non-STL
...

 
Peterchen mentioned Meyers probably because of his article STL Algorithms vs Hand-Written Loops[^] in which he generally favors the use of algorithms rather than loops.
 
However, I would agree with Meyers' conclusion on this matter:
 
In the ongoing tussle between algorithm calls and hand-written loops, the bottom line on code clarity is that it all depends on what you need to do inside the loop. If you need to do something an algorithm already does, or if you need to do something very similar to what an algorithm does, the algorithm call is clearer. If you need a loop that does something fairly simple, but would require a confusing tangle of binders and adapters or would require a separate functor class if you were to use an algorithm, you’re probably better off just writing the loop. Finally, if you need to do something fairly long and complex inside the loop, the scales tilt back toward algorithms, because long, complex computations should generally be moved into separate functions, anyway. Once you’ve moved the loop body into a separate function, you can almost certainly find a way to pass that function to an algorithm (often for_each) such that the resulting code is direct and straightforward
 


My programming blahblahblah blog. If you ever find anything useful here, please let me know to remove it.
 
GeneralHeron Pin
Thursday, August 12, 2004 3:47 AM by Nemanja Trifunovic
I am aware of at least three bad attempts to fix C++: Java, C# and D. Some would argue that Managed C++ (C++/CLI) is one of these attempts as well, but I just view it as a set of extensions to C++, not a new programming language.
 
Now, I found Heron[^], and so far I like what I see.
 
The main problem with Heron is that it is just another one-man project, and it has close to zero chances of ever becoming mainstram. So far the author has released a Heron front end that converts Heron to C++, an editor, and some (pretty poor and incomplete) documentation.
 
Having said all of that I really like the philosophy of Heron and most of its features:
 
- No backward compability with C and all the problems that come with it.
- No virtual functions; polymorphism is achieved through interfaces
- All fields are private
- Support for value semantics, real destructors and deterministic finalization
- No built-in garbage collector
- Rich support for meta-programming
- Support for AOP and design-by contract.
 
It is a pitty that Microsoft decided to copy Java when they designed C#. Something like Heron would be a much better solution, IMHO.
 


My programming blahblahblah blog. If you ever find anything useful here, please let me know to remove it.
GeneralRe: Heron Pinmembercdiggins12 Aug '04 - 10:56 
GeneralRe: Heron PinmemberNemanja Trifunovic13 Aug '04 - 8:22 
GeneralRe: Heron Pinmembercdiggins13 Aug '04 - 8:52 
GeneralRe: Heron PinmemberMr.Prakash26 Sep '04 - 8:09 
GeneralRe: Heron PinmemberMystifier0028 Jan '05 - 18:22 
look at Ruby, you will love it
 

 
mystifier
GeneralRe: Heron PinmemberNemanja Trifunovic29 Jan '05 - 4:58 
GeneralRe: Heron PinmemberJim Crafton14 Mar '05 - 4:55 
GeneralRe: Heron PinmemberNemanja Trifunovic16 Mar '05 - 1:48 
GeneralRe: Heron PinmemberJim Crafton16 Mar '05 - 3:42 
 
GeneralVS 2005 Non-Express Beta 1 Pin
Sunday, August 1, 2004 4:28 AM by Nemanja Trifunovic
Yesterday, I installed "full" version of VS 2005 Beta 1. Installation went smoothly, which surprised me a bit, because I heard some horror stories before. Anyway, since VC++ 2005 Beta is not in a state that would allow me to do anything serious with it, I started playing with C#.
 
First topic: generics, of course. Here is my "generic hello world":
 
namespace Generics
{
	class MyArray<T>		
		{		
		public MyArray(int size)
			{ data_ = new T[size]; }
		public T this[int index]
		{
			get { return data_[index]; }
			set { data_[index] = value; }
		}
		private T[] data_;
		}
	
	class Program
	{
		static void Main(string[] args)
		{
			MyArray<string> strArray = new MyArray<string>(10);
			strArray[0] = "First";
			strArray[1] = "Second";
		}
	}
}
 
Couple of things to notice at a first glance:
 
1. Angle brackets are used for type parameters like in C++, and unlike in D where ordinary brackets are used
2. Generics accept only type parameters - no nontype parameters and generics. I'll need to investigate the consequences of this further.

 


My programming blahblahblah blog. If you ever find anything useful here, please let me know to remove it.
 
GeneralHow to use C++/CLI? Pin
Friday, July 23, 2004 2:52 AM by Nemanja Trifunovic
I looked again at the code I posted earlier (it does not compile with Beta 1):
 
System::IO::StreamReader file(L"test.txt");
String^ line = file.ReadLine();
Console::WriteLine(line);
 
Is this really what I want to do with C++/CLI? I don't think so. In practice, if I want to read a line from a file and write it to the console, I'll do something like this:
 
ifstream file ("test.txt");
if (file.is_open())
    {
    string line;
    getline(file, line);
    cout << line << endl;
    }
 
Why do I need C++/CLI then at all? Well, the world is moving towards .NET and managed environments and I don't want to stay behind. On the other hand, I don't partculary like the .NET object model and BCL, and I want to use "classic" C++ whenever possible.
 
A solution is to develop my "core logic" code in standard C++, and then to expose it to the .NET world through an interface (or "Facade", if you prefer GoF terminology).
 
I see three ways to do that. One is to "flatten" my facade classes and expose them as a set of C functions, which can be called through PInvoke. Another would be to make COM wrappers. Finally, I can use Managed C++ or C++/CLI to easily write CLS compliant wrappers for my facade classes. COM wrappers is something I would rather avoid, which leaves me with C vs MC++ dilemma. The "C" approach appeals me because it enables other non - .NET languages to use the libraries. On the other hand, if I care only about .NET, with Managed C++ I can create classes that can be used from .NET languages directly, without PInvoke hassles.
 
The bottom line is: C++/CLI is about making C++ code available to .NET world, and if it is easy enough to do that, than I don't necesseraly care about deterministic finalization, STL.NET and other cool programming techniques. I'll just use ISO C++ for that.
 


My programming blahblahblah blog. If you ever find anything useful here, please let me know to remove it.
GeneralRe: How to use C++/CLI? PinprotectorNick Parker29 Jul '04 - 9:20 
GeneralRe: How to use C++/CLI? PinmemberNemanja Trifunovic29 Jul '04 - 13:58 
GeneralRe: How to use C++/CLI? PinprotectorNick Parker29 Jul '04 - 17:29 
 
GeneralMy first hands on experience with generics Pin
Saturday, July 17, 2004 8:41 AM by Nemanja Trifunovic
Back to my VC++ 2005 Express Beta 1. Today, I am going to play with generics a little bit.
 
I started with this:
 
interface class I { int f(); };
 
generic <typename T> where T : I
ref class GenericClass {};
 
So far, so good. Compiles fine. Now, I tried to add a member, like this:
 
interface class I { int f(); };
 
generic <typename T> where T : I
ref class GenericClass 
  {
  T^ data_;
  };
 
Ooops:
 
First.cpp(15) : error C3229: 'T1 ^' : indirections on a generic type parameter are not allowed
        compiler using 'T1' to continue parsing
 
Now, this T1 is confusing, but anyway if I modify my class to look like:
generic >typename T< where T : I
ref class GenericClass 
  {
  T data_;
  };
everything looks fine. Then I tried to add a constructor and instantiate the thing:
 
interface class I { int f(); };
ref class C: public I
{
public:
  int f() {return 0;};
};
 
generic <typename T> where T : I
ref class GenericClass 
{
  T data_;
public:
  GenericClass (T data) : data_(data) {}
};
 

int main()
{
	C^ c = gcnew C;
	GenericClass<C^> g = gcnew GenericClass<C^> (c); 
}
 
and the result is:
 
First.cpp(29) : error C3149: 'GenericClass<T&gt' : cannot use this type here without a top-level '^'
        with
        [
            T=C ^
        ]
 
Cry | :(( This is frustrating...
 


My programming blahblahblah blog. If you ever find anything useful here, please let me know to remove it.
 
GeneralBad habits of "old-style" programming Pin
Tuesday, July 13, 2004 3:05 AM by Nemanja Trifunovic
At one point (end of 2003), the web was full of blogs from some very interesting people, like Herb Sutter, Brandon Bray, etc. However, it seems that most of them gave up blogging soon. Stan Lippman is "the last man standing" in this regard, and I try to keep an eye on his blog.
 
One thing I found on his blog was the next piece of code (from this article[^]:
 
    char *ch = new char[ len ];
    bool result = wcstombs( ch, wch, len ) != -1;
    target = ch;
    delete ch;
 
See the last line? It should really be:
    delete[] ch;
 
In fact, why did Stan even use this new[]...delete[] construct here? Modern C++ offers this alternative:
 
    vector<char> ch(len);
    bool result = wcstombs( &ch[0], wch, len ) != -1;
    target = &ch[0];
 

Stan's explanation: it is a bad habit for an old dog who was programming with the language before this was added, and of course in current implementations, its absence is actually both non-fatal and possibly more efficient.
 
This makes me wonder. If a master like Stan Lippman makes a mistake like this, something is wrong here. Old dog's habits are hard to get rid of. Maybe we really need a new, smaller and cleaner language, after all - a language that would inherit the power of C++ but leave the C heritage behind. The problem is - I don't know such a language - Java and C# are definitely not what I have in mind.

 


My programming blahblahblah blog. If you ever find anything useful here, please let me know to remove it.
 
GeneralC++/CLI - ref objects on native heap Pin
Sunday, July 11, 2004 7:11 AM by Nemanja Trifunovic
Still playing with VC++ 2005 Beta 1.
 
Today I tried to compile the following code:
 
ref class Widget {};
 
int _tmain()
{
  Widget^ managed = gcnew Widget;
  Widget* native = new Widget;
}
 
Yes, I forgot to type gcnew again, but what I wanted to say is that
according to Nick Hodapp[^], this should compile just fine. Guess what? I got error C2750: 'Widget' : cannot use 'new' on the reference type; use 'gcnew' instead.
 
Another C++/CLI feature that didn't make into Beta 1? I really feel I'm wasting my time here Mad | :mad:
 


My programming blahblahblah blog. If you ever find anything useful here, please let me know to remove it.
GeneralRe: C++/CLI - ref objects on native heap PinmemberBrian
Olej
11 Jul '04 - 7:27 
 
GeneralRAII with C++/CLI Pin
Saturday, July 10, 2004 10:11 AM by Nemanja Trifunovic
I wrote the next piece of code today:
 
System::IO::StreamReader^ file = new System::IO::StreamReader(L"test.txt");
String^ line = file->ReadLine();
Console::WriteLine(line);
file->Close();
 
and got the compiler error error C2750: 'System::IO::StreamReader' : cannot use 'new' on the reference type; use 'gcnew' instead.
 
Of course, of course... even with old MC++ I would usually type
System::IO::StreamReader __gc* file = __gc new System::IO::StreamReader(S"test.txt");
, but it is still too easy to forget. Anyway, if we correct this typo, we end up with:
 
System::IO::StreamReader^ file = gcnew System::IO::StreamReader(L"test.txt");
String^ line = file->ReadLine();
Console::WriteLine(line);
file->Close();
 
It compiles and runs fine. However, I would never put something like this into production code. Why? Because StreamReader::ReadLine() can throw an exception, and if it does we have a resource leak - the file never gets closed. One way to make this code exception safe is to rewrite it like this:
 
	System::IO::StreamReader^ file = nullptr;
	try
	{
		file = gcnew System::IO::StreamReader(L"test.txt");
		String^ line = file->ReadLine();
		Console::WriteLine(line);	
	}
	finally
	{
		if (file != nullptr)
			file->Close();
	}
 
 
Now, that is too much work, and many developers are just too lazy to write the finally clause. In fact, I can't really blame them. This is way too tedious way to make your code exception safe.
 
Tha right way to take care about resource management is a technique called RAII. If you don't know much about RAII, I strongly encourage you to read this article by Jon Hanna[^]. This idiom is so simple and effective that I even consider keyword finally a flaw in a programming language, because it is either a sign that RAII is not supported, or encourages developers not to use it.
 
The problem is that RAII does not go well with nondeterministic GC envirinments. For instance, it is impossible to implement it in Java or VB.NET 2003. In C#, there is using keyword wich enables some kind of poor man's RAII mechanism, but even that is too much work IMHO, and I know some C# developers who just don't get why they should bother with using. Even more, in the first edition of Professional C#[^] the author recommends avoiding using which is IMHO a crime.
 
In old MC++, there is no built in support for RAII. However, I wrote a template class[^] that gives developer a possibility to use RAII, although with some performance cost.
 
One of the big things about C++/CLI is supposed to be the return of deterministic finalization and support for RAII. Having read an interview with Nick Hodapp[^], I expected to be able to modify my code like this:
 
	System::IO::StreamReader file(L"test.txt");
	String^ line = file.ReadLine();
	Console::WriteLine(line);
 
but I got error C3149: 'System::IO::StreamReader' : cannot use this type here without a top-level '^'. Huh? How do we use deterministic finalization with C++/CLI? I'll try to investigate this, and get back to you later.
 


My programming blahblahblah blog. If you ever find anything useful here, please let me know to remove it.
GeneralRe: RAII with C++/CLI PinmemberNemanja Trifunovic10 Jul '04 - 10:19 
 
GeneralTrivial (and less trivial) properties Pin
Friday, July 9, 2004 9:36 AM by Nemanja Trifunovic
One of the new features of C++/CLI is trivial properties. Basicaly, the code:
 
class SomeClass
{
  public:
  property int State;
};
 
translates to:
 
class SomeClass
{
  public:
  property int State 
    {
    int get() const
       { return State_; }
    void set(int value)
       { State_ = value; }
    }
private:
  int State_;
};
 
Now, to be quite honest with you, I don't like properties. Not because I believe they hurt encapsulation like some people do[^]. No, properties per se don't hurt encapsulation any more than other member functions do. What I don't like about them is the syntax: they are really methods, but you call them as if they were public fields. Maybe it is because I work with linguists a lot these days, but I firmly believe that good functions' names are verbs ( DoSomething() ) and that good variables' names are nouns ( someValue ). In my mind object.SetSomething(value); is much better than object.Something = value; .
 
As for encapsulation, as I said - properties don't have to hurt it at all. Abstraction, yes - just as much as accessor functions hurt abstraction, but this is another story.
 
BTW, does anybody know why Java and C# even allow public fields?
GeneralRe: Trivial (and less trivial) properties PinmemberJörgen Sigvardsson11 Jul '04 - 10:12 
GeneralRe: Trivial (and less trivial) properties PinmemberNemanja Trifunovic11 Jul '04 - 12:01