-1

Say for example I have a function that returns a value from a 2-dimensional array:

float get_2d_noise(const point& p)
{
    return map2D[p.x][p.y];
}

The point is a class that I've defined as part of my library:

struct point
{
    int x;
    int y;
}

Aside from doing this:

template<typename T>
float get_2d_noise(const T& p)
{
    return noisemap[p.x][p.y];
}

Is it possible to get the same effect? I.e., create get_2d_noise in such a way that anything with an x and y member will work? (preferably catching errors at compile time, rather than runtime).

NeomerArcana
  • 1,978
  • 3
  • 23
  • 50
  • 6
    what do you want to do that you cannot do with a template ? – 463035818_is_not_an_ai May 06 '16 at 12:22
  • 1
    btw the function will only work if `T`s x and y members can be converted to an `int` – 463035818_is_not_an_ai May 06 '16 at 12:25
  • Theoretical Computer Science would suggest yes. Both C and C++ are Turing Complete languages, meaning one is just as powerful as the other. C++ has templates and C does not. Therefore we can conclude that C can support generic programming sans templates. – erip May 06 '16 at 12:29
  • @erip Theoretical Computer Science would suggest nothing. Programming languages theory generated a vast amount of Turing-equivalent languages which have different expressiveness. (What would you call "generic programming" in Turing Machines, for instance?) – chi May 06 '16 at 12:36
  • @chi Expressiveness and power are different, are they not? :) NFAs and DFAs are equally powerful, but NFAs are markedly more expressive. Turing Machines know nothing about semantics - just flips and shifts. – erip May 06 '16 at 12:41
  • 1
    @KarolyHorvath I'm grabbing my pitchfork!!! You'd better apologize. – erip May 06 '16 at 12:47
  • @erip: good luck with your remote pitchfork project. – Karoly Horvath May 06 '16 at 12:58
  • @tobi303 basically I'm wondering if theres a way to give the affect of template type without forcing the user to write longer code. – NeomerArcana May 06 '16 at 13:42
  • what do you mean with longer code? Writing a template is much shorter than providing the instantiation for each type explicitly. If you are worried about the user having to type `get_2d_noise` instead of just `get_2d_noise`, this is not an issue, because the type can be infered. Dont try to be more clever than the language just to have less to type – 463035818_is_not_an_ai May 06 '16 at 13:51
  • @tobi303 so `get_2d_noise(valueOfSomeType)` will work even with a templated function? – NeomerArcana May 06 '16 at 14:00
  • My knowledge about the rules of inferring template parameters is rather limited. Actually I personally prefer to write the type, imho that makes it easier to read the code in some cases. However, I would expect that for this example the type can be inferred easily. If you pass `someType` as parameter, the instantiation for `someType` will be used. E.g. for return types this wont work – 463035818_is_not_an_ai May 06 '16 at 14:05
  • .. please dont accept my answer. It was just meant to show one way how you should not do it, and actually in the comments there is a discussion on going whether macros should be considered as generic programming at all. I think you should improve your question by stating clearly what you want to do and why you think templates arent good for that, before a good answer can be given – 463035818_is_not_an_ai May 06 '16 at 14:09

4 Answers4

4

You may cheat with generic lambda (c++14), so you don't use explicitly template:

auto get_2d_noise = [&](const auto& p) -> float
{
    return map2D[p.x][p.y];
};
Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • 1
    This isn't really "without templates" – Barry May 06 '16 at 12:56
  • These are lambda templates. They get instantiated, so it's still using templates :-) – Nikos C. May 06 '16 at 13:00
  • @Barry: It is without the *keyword* `template`, even if, it turn out to be equivalent to `template` at the end. (That's why I use "cheat"). – Jarod42 May 06 '16 at 13:25
  • I should have been more explicit about "not using templates". It's fine to use templates, so long as the person invoking the function isnt aware of it. This would match that. However c++14 is outof my reach for now – NeomerArcana May 06 '16 at 13:43
  • @NeomerArcana: What do you mean "isnt aware of it?" What ways would such a person become "aware of it" are you concerned about? Because the differences between calling a template function and calling a non-template function aren't particularly burdensome most of the time. – Nicol Bolas May 06 '16 at 15:08
0

One possibility woud be to be syntactically explicit about what youw want to do. You could create an interface IPoint or similar (which in C++ can be done using an abstract class) where you define getters for your data members, say GetX and GetY; then you could formulate your function as follows.

float get_2d_noise(const IPoint& p)
{
    return noisemap[p.GetX()][p.GetY()];
}

That way, you would not have to use generics; instead, you would use inheritance. However, any type you would like to use with get_2s_noise would have to be derived from IPoint (and implement the getters in a meaningful way), but that seems to be what you are looking for.

Codor
  • 17,447
  • 9
  • 29
  • 56
  • It is an answer to the question, therefore +1. However, I do not think this is what he is looking for. It seems like a terrible idea to me to define an interface. Hopefully, naturally in his design, all object that he wants to call the function for already has the same base class. – Bernhard May 06 '16 at 12:40
  • Well thanks for the comment; why would you find it terrible to define an interface? – Codor May 06 '16 at 12:42
  • 1
    You have to update any class where you want to make the function work. – Bernhard May 06 '16 at 12:45
0

Is it possible to get the same effect? I.e., create get_2d_noise in such a way that anything with an x and y member will work? (preferably catching errors at compile time, rather than runtime).

This is literally the entire point of the existence of templates: they were created in order to support generic programming in C++. So no, there isn't another way to write templates in C++ outside of writing templates.

Barry
  • 286,269
  • 29
  • 621
  • 977
  • "there isn't another way to write templates in C++ outside of writing templates" - obviously true. but also irrelevant. You have just reframed the question. – Karoly Horvath May 06 '16 at 12:49
  • @KarolyHorvath That is literally the question. – Barry May 06 '16 at 12:50
  • @Karoly Jarod's answer uses templates. The other two are not generic programming. – Barry May 06 '16 at 12:55
  • how is a macro not GP? From wikipedia: "In the simplest definition, generic programming is a style of computer programming in which algorithms are written in terms of types to-be-specified-later that are then instantiated when needed for specific types provided as parameters." – Karoly Horvath May 06 '16 at 13:05
  • @KarolyHorvath Not a lot of type abstraction in macros. And they don't get instantiated - you have to manually instantiate them with all the types you think you need. Unless you're giving a cheeky obfusticated-code-competition answer, macros are not gp. – Barry May 06 '16 at 13:41
  • I should have been more explicit. It's fine to use templates, but the invoker of the function shouldnt be aware of it – NeomerArcana May 06 '16 at 13:45
  • @Barry: sigh. replace the function with an expression, and you don't have to manually instantiate. – Karoly Horvath May 06 '16 at 13:47
  • @NeomerArcana: don't put that comment here. And post code for actual usage, because your comment doesn't make sense.... – Karoly Horvath May 06 '16 at 13:49
  • @KarolyHorvath How's that `max(++x,y)` macro working out for you? – Barry May 06 '16 at 13:52
  • @NeomerArcana Why would that matter? – Barry May 06 '16 at 13:52
  • @barry I guess it doesnt much. I'm just wondering if it's possible – NeomerArcana May 06 '16 at 14:01
  • @Barry: you mean `MAX`, with all caps, as in 'danger ahead'? – Karoly Horvath May 06 '16 at 14:37
0

You could write a macro that takes the name of the type as parameter and then creates the desired function. Something like

CREATE_2D_NOISE_FOR(someType)

that gets expanded to

float get_2d_noise(const someType& p) {
    return noisemap[p.x][p.y];
}

However, this is highly not recommended, as you loose all the expressiveness of templates and gain all the problems that come with macros.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185