-2

I have a pretty simple code as the following.

template<typename T>
struct cell{
    int nr;
    T*  someInfo;
};

template<typename T>
void doSomething(cell<T> c)
{
    cout<<c.nr;
}

I actually have numerous functions using cells, very few using the T* template info (above code does not use it). Can I write my program (in C++98) without ending up with countless template keywords, T* or cell stuff? I want to reduce clutter, to write a rather C-like C++ code, easy to read by those who are not familiar with C++. Can I make the compiler understand (without macros) that whenever it sees cell, it is actually cell<T> and it has to put a template on the function?

If there is no C++98 solution, I prefer a C way using void* instead of T*. That comes with no clutter in the rest of the code, but I can't delete c.someInfo, but only free(c.someInfo).

7
  • 1
    You might use inheritance, the non template part in the non template base.
    – Jarod42
    Commented Jan 17, 2018 at 10:14
  • 5
    Why not just write good C code instead of bad C++ code? new and delete call malloc and free under the hood, so you're not really "gaining" anything.
    – user167921
    Commented Jan 17, 2018 at 10:19
  • 1
    easy to read by those who are not familiar with C++ My experience is that this is a bad idea. Not only do those not familiar with C++ learn about it as they read it, but the code ends up more complex than it needs to be so even those who ARE familiar with C++ end up getting confused.
    – UKMonkey
    Commented Jan 17, 2018 at 10:26
  • 4
    To paraphrase Mr. Miyagi: "Write C++, safe. Write C, safe. Write C-like C++, sooner or later, get stack smashed" Commented Jan 17, 2018 at 10:28
  • Regarding the C-like C++, I only want WYSIWYG C++ where I have control over what happens when the code is executed. This is cited as an advantage of C over C++, as in the second point of this answer. See other reasons for C-like C++ in the answer of user Solifugus to the C++ criticisms of M. Torvalds. Commented Jan 17, 2018 at 11:16

5 Answers 5

4

Reuse code by inheritance from a non-templated base class.

struct cell_base {
  int nr;
};

template<typename T>
struct cell : cell_base {
    T*  someInfo;
};

void doSomething(cell_base const& c)
{
    cout<<c.nr;
}

So whatever needs the non-templated bits accepts a cell_base, and the few things that do need the template parameter can be templates.

2
  • 1
    Yes, that is a nice idea. Didn't think of that (despite doing it in a couple of places in my code, although not to save typing).
    – Bathsheba
    Commented Jan 17, 2018 at 10:15
  • Nice idea indeed. This can solve almost half of my problems. It is still possible to call doSomething(..) on a cell object. Commented Jan 17, 2018 at 11:33
2

If you want to use templates, then you need to use the correct template syntax.

Which does indeed mean writing T quite a few times as well as template<typename T>. That's life: the compiler does some very clever things, and needs this "boilerplate" in order to disambiguate.

You can reduce the amount of typing by writing all the functions inline inside the class declaration.

Using (void*) instead would be anachronistic.

1

You can typedef your template; and which will completely hide the fact that it's a template for a specific type. ie

typedef cell<int> IntCell;

then usage of the type

void doSomething(const IntCell& c) {}
2
  • Indeed, ok; but as you said, this works for a specific type. As long as I can not write typedef cell<T> TCell this is not fully satisfactory. Commented Jan 17, 2018 at 10:47
  • @DanielPorumbel and I hope this explains why in the question you should say what you tried. There's nothing indicating that you couldn't there.
    – UKMonkey
    Commented Jan 17, 2018 at 11:10
0

Edit: I now realize that you asked about c++98. My suggestion requires c++14 unfortunately.

You could use generic lambdas in place of template functions:

auto doSomething = [](auto c) {
    cout<<c.nr;
}

If you're willing to wait for a bit, there is the concepts proposal for the C++ standard which will hopefully be included in C++20. It includes generic functions which could allow:

void doSomething(auto c)
{
    cout<<c.nr;
}

Or

void doSomething(Concept c)
{
    cout<<c.nr;
}

Where Concept is a concept that all cell<T> satisfy. This is a compile time analogue to the runtime inheritance suggested by StoryTeller.

2
  • Question asks for C++98 Commented Jan 17, 2018 at 11:40
  • @MartinMeeser To be honest, I skipped the question body text entirely. Oh well, this may be useful to others.
    – eerorika
    Commented Jan 17, 2018 at 11:42
-1

Hoping this can be useful for somebody someday, I'll explain why I ended up with the old-school C solution in C++. You maybe need to be in the same mess as me to understand, i.e., you need to deal with some minor unknown pointer for which you do not want to clutter a C++ code which already has many classes that can not be ported to C in reasonable time. I thank all the responses I received, and after considering them, I regret they could not solve my problems. Even with inheritance, I still end up with hundreds of template and <T> stuff because I have many classes and sub-classes with cell members.

It is easier/cleaner to use void* someInfo as in C, as that does not require modifying all classes that contain cells. The problem of deleting the void* pointer is left to the user of the library. It's easy to allow/ask the user to make a unique call like set_func_free_info(&custom_free_func). The deallocation function of the library could be:

if(func_free_info!=NULL) 
    func_free_info(c.someInfo);
else                    //don't let it get here if someInfo points to an object
    free(c.someInfo);   //needing a destructor, do use set_func_free_info(...).

Given some of the responses, I feel you :

  • might argue void* is "anachronistic". Maybe. If somebody told me that such an old language like English is anachronistic faced to modern Esperanto, I would feel the same.
  • might say it is a bad idea to write code somehow for pure C programmers not familiar with C++, in the line with a above remark ``the code ends up more complex than it needs to be so even those who ARE familiar with C++ end up getting confused.''. If you honestly think about this, here the opposite is true : the code is less complex by avoiding C++ features, as the template constructs would clutter all the code for a minor feature.
  • ask why don't stick to pure C and simply finish the story. I can't, because this is part of a code where someInfo can be an object. So I end up with the C-like C++ style that some here seem to hate, but you can really find reasons for it on the linked material my comment above.

Anyway, M Stroustrup said that

C++ is deliberately designed to support a variety of styles rather than a would-be "one true way".

So if you like to lecture about "your true C++ way", you should understand you shouldn't do it. And you'll see life so much more than a foolish game. C++ supports infinitely many more styles and possibilities than C, e.g., I could use lambdas as in one of the replies, but too many would not understand it.

2
  • Type-safety just went out the window.
    – Johan
    Commented Jul 25, 2022 at 13:32
  • I do not care, this is theory stuff, I like down-to-earth practicalities. Many libraries become slower and slower with each version because they never stop introducing features like thread-safety, type-safety, xxx-safety, each time sacrificing the speed (see also software bloat). Commented Dec 30, 2022 at 16:31

Not the answer you're looking for? Browse other questions tagged or ask your own question.