A C++ and templates vs C and Macro discussion

Go To Last Post
7 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I start by apologising myself for this topic.

In fact, the only reason for its existance is not to polute my ather topic which has its own objective, but as so many ones were concerned with this related discussion, I planned to branch it here.

For reference, here is the original thread:
https://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=72783&start=0&postdays=0&postorder=asc&highlight=

And I will begin by replying ArnoldB's.
Sorry if I seem impolite someway...[/url]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

> Show evidence,

> 1. that your way provides more flexibility (might require to produce a definition of "flexibility" first)

In standard C programming anyone has ways of splitting hardware dependent code from hardware independent. It is done broadly in several good projects like FreeRTOS, Linux, bla, bla, bla.
It is a _project_ related matter.
The point of note is that this code must be explicitly implemented for every minor difference.

A change from PORTA to PORTB must be coded and selected thru #ifedefs and only then it can be used.

In my effort, this implementation is not needed. When one instantiate a templated device using PORTA or PORTB, the generic code is already implemented, and the specific one is generated by the C++ compiler.

One can have, in the same application and without the need to code anything else, more than one instance of the same device class just by declaring it!

More than it, in different versions of hardware, the system configuration can be done by the correct template parametrization in a single place instead of several conditional definitions and inclusions.

If it is not flexible, I really assume my ignorance. You can stop reading it and save your time.

> 2. that your kind of flexibility is needed and wanted in the majority of MCU code and projects

I don't care about every single developer's need in the world. I care about mine and my team.
I see that we are mature enough to experiment some steps forward and try to solve several issues that concern to our projects for a long long time. based on hundred pages found in a single "googled", I cannot doubt that those points affect only me, so I conclude that it is not a bad idea to share my thoughts with others that my take any advantage, doesn't matter how they will use it.
If anyone else in the planet (or outside it) thinks that the current solution is good enough for their needs, fine, I won't bother them for it. there's no need for anyone to make what I do.

> 3. that defines lack the flexibility you want to provide

Isn't this question already discussed in 1?

> 4. that defines are difficult / bad to maintain

If all the above is already read, read 6 and 8.

> 5. that your solution is better to maintain, particular in the light of the ugly C++ template syntax and "tons of typedefs" to hide the template syntax

There are a bunch of articles talking about the differences between #define and typedef. The following one says everything.
http://www.ddj.com/cpp/184403271

If you stand that "#define" is better than "typedef", it can be useful to read the link.

This link is also useful:
http://yosefk.com/c++fqa/picture...

The maintenance matter is considered below.

> 6. The same as 5. but taking the maintenance of your template library vs. garden-variety defines into account

Oh Christ!
How can be an object-oriented, type-safe and generic approach be better than a macro based one?
Are you kidding or you are happy enough with what you have to never have tried anything else?

Object orientation increases encapsulation, modularization and reusability. I can't believe that exist a person in the world that can arguably state otherwise.
Templated or generic programming, augments reusability even more.

The rationale behind it is that you can reach a common and standardized structure that will much often be reused.
Once a common code base is reused, one can take profit of it have already been debugged. The development is always incremental. Base classes will not be changed all the time, unless its project is misconcepted.
Macro-based implementation gives no mechanisms to control relations among related concepts. This responsability is encharged to the implementor, so any change must be verified and propagated manually. Not doing the correct adjustments may lead to a code that compiles perfectly, but is completely messed.

> 7. that defines are more difficult to read and understand than your templates and typedefs

Of course, if you are thinking on a C programmer, anything related to C++ will be harder/uglyer/worse than what this programmer knows.

> 8. that flexibility is a fix for the alleged maintenance problem and the implied "defines are difficult to read" problem. Explain why orthogonal concepts like flexibility and maintenance are related in the general case and for the majority of MCU projects

Read 2.
And it may be time to ask you to show evidence that flexibility and maintenance are orthogonal concepts.
A generic solution IS flexible and MORE easy to mantain that custom ones.
If you can't see this, think about a simple circular list or something like.
If you have a custom list for every kind of data you may want to use, you must implement every single method to interact with it. Implement, debug and maintain. A change in one particular solution should be propagated to the other correlated ones, but no one can assure it.
If you have a generic solution, you'll end up having just ONE implementation. How can maintenance be easier?

> 9. that "C++ templates ... full of tricks" (your words) simplifies maintenance, especially in the light that it raises the competence bar for the maintainer (must be familiar with the particular tricks applied when hunting a bug which could well be because of the C++ template tricks applied)

Or in short, I think what you do is what many years ago one of my professors characterized as "academic w*nking" (yes, those were the times before political correctness). Nice to do on occasion, temporary entertaining, but otherwise doesn't serve the real purpose.

Competence is a must. If a programmer doesn't have it, it won't be able to act in this kind of project.
We are aboarding the scond decade of the XXI century. Structured paradigm is something trivial. Object orientation and related knowledge is mature and earns room in applications that weren't feasible 20 years ago. If you think that there's no need to improve anything in your projects, fine! I won't bother you!
I think that several things can be improved, profiled or, at least prooved. If the experiments don't lead to a valueable enhancement, it will be discarded, but it is no excuse for no trying!
Humanship could live in caves, it was quite warn inside it!

> BTY: It is "syntax", not "sintax"

Thanks a lot, Sir, and I recognise and apologise for my mistake. I was in ignorance, now you gave me some light.

http://www.thefreedictionary.com...

syn·tax (sntks)
n.
1.
a. The study of the rules whereby words or other elements of sentence structure are combined to form grammatical sentences.
b. A publication, such as a book, that presents such rules.
c. The pattern of formation of sentences or phrases in a language.
d. Such a pattern in a particular sentence or discourse.
2. Computer Science The rules governing the formation of statements in a programming language.
3. A systematic, orderly arrangement.
[French syntaxe, from Late Latin syntaxis, from Greek suntaxis, from suntassein, to put in order : sun-, syn- + tassein, tag-, to arrange.]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

> BTY: It is "syntax", not "sintax"

To further cloud the issue, note that "sin tax" has its own Wikipedia entry :twisted:
http://en.wikipedia.org/wiki/Sin...

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
the system configuration can be done by the correct template parametrization in a single place
An example? The example from your other thread IMO can be better handled with a simple class, without templates. And, don't you need #ifdefs regardless of C vs C++?
Quote:
"sin tax"
All taxes are sinful, therefore this is redundant!

C: i = "told you so";

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Taking another UART implementation example:

template< UART_BaseAddr base, uint8_t RxBufferSize = 32, uint8_t TxBufferSize = 32 >
class	UART	:	public CharDev
{
public:
	bool	get( char &c );
	bool	put( char c );
	int		puts( const char *s );

	inline void enable( TX_RX_flags tx_rx )	const
	{	Regs::UCSRB( ) |= tx_rx;	}

	inline void disable( TX_RX_flags tx_rx )	const
	{	Regs::UCSRB( ) &= ~( tx_rx );	}

	inline void enable_irq( IRQ_flags tx_rx )	const
	{	Regs::UCSRB( ) |= tx_rx;	}

	inline void disable_irq( IRQ_flags tx_rx )	const
	{	Regs::UCSRB( ) &= ~( tx_rx );	}

	bool	open( );
	void	close( );
	bool	isOpen( );

	int32_t	baud( )	{	return _baud;	}
	void	baud( int32_t b );

protected:
	static int32_t			_baud;

	Queue< char, uint8_t, RxBufferSize >	rx;
	Queue< char, uint8_t, TxBufferSize >	tx;

	void startXmit( );
	void stopXmit( );

	/// USART Registers.
	class Regs
	{
	public:
		static Register_reference	UCSRA( )
		{	return	*( Register_pointer )base;	}

		static Register_reference	UCSRB( )
		{	return	*( Register_pointer )( base + 1 );	}

		static Register_reference	UCSRC( )
		{	return	*( Register_pointer )( base + 2 );	}

		static Register_reference	UBRRL( )
		{	return	*( Register_pointer )( base + 4 );	}

		static Register_reference	UBRRH( )
		{	return	*( Register_pointer )( base + 5 );	}

		static Register_reference	UDR( )
		{	return	*( Register_pointer )( base + 6 );	}
	};

public:
	void isr_rx( );
	void isr_txe( );
};

If I was to do a simple class, I'd have to code a UART class for each UART in my MCU (some AVR have 4 of it).

In this example I have the very same class for any UART.
I just have to declare an object like this:

UART< Base_UART2 >	uart2;

And all the needed adaptations will be done automatically by the compiler. No bothering with fitting register names, etc.

Any instance of my class knows it has a UCSRB register that may be accessed as I do in:

inline void enable( TX_RX_flags tx_rx )	const
{	Regs::UCSRB( ) |= tx_rx;	}

If I change something (add some feature, fix some bug) I just need to do it once, and not for all the different kinds or UART in my system.

It is also important to note that the generated code has no overhead. It will be as good as done with direct register calling in the specific code.

I don't know if anyone else believes or agrees, but it is enough for to justify my effort.

Similar tasks can be taken for other kind of classes, of course, not just my silly example, so, don't blame for this. Anyone clever may think in something more useful.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes, I can see the value of such an approach. Minor detail: can peripheral register mapping be assumed to follow your example:

*( Register_pointer )( base + 6 );

However, I still think templates may be overkill for a single register (e.g. DDRx).

C: i = "told you so";

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I also am not sure if templates is the best way to go here. However I do agree that C++ programmers should do away with macros as much as possible. The feature set of C++ eliminates the need for the vast majority of macros.

The problem with macros is that the compiler can not evaluate them. It can only evaluate the result of a macro that is handed to it by the pre-processor. Thus you end up in situations where you have to add:

do { ... } while(0)

around your macro to make sure that the user doesn't, God forbid, use a ';' in a place that he shouldn't.

Quote:
And, don't you need #ifdefs regardless of C vs C++?

Yes. There are many times that you need compile time switches.

Quote:
All taxes are sinful, therefore this is redundant!

But if taxes are a sin and you have a sin tax, you have a recursive situation. I guess the end condition for that is when you run out of money :)

Regards,
Steve A.

The Board helps those that help themselves.