C++ Templates

Posted by Rusky on March 2, 2011, 5:47 p.m.

… are idiotic of the devil. Not the idea necessarily, just the details. Pop quiz:

Given this template declaration:

double foo(double);

template <class T>
class Test {
public:
    void invariant() { member = foo(val); }
    T dependent() { return foo(member); }

private:
    int val;
    T member;
};

and this instantiation:

int foo(int);

Test<int> test;

which instance of foo will be called here?

test.invariant();
test.dependent();

The answer: Both. FFFFFFFUUUUUUUUU-

Because the invocation of foo() in the method invariant() is only dependent on the type of val, which is not a template argument but the same type for all instantiations of Test<T>, it is resolved using the declaration scope to foo(double). Perfectly reasonable.

However, for some reason, the designers of C++ decided that the scope of a template instantiation should influence the decision of how to resolve overloaded functions inside the class.

Because the the type of the argument to foo() in dependent() is a template argument, it is unknown until instantiation time. This apparently means the compiler should fling in the scope in which Test is instantiated, just because it can't do a complete type check until it knows the type arguments. Thus, dependent() will call foo(int), which is completely out of scope at the definition of Test.

Why, for the love of all that is sane, would you ever mess with scope that way? Even worse, why would you ever make it different in different situations?

Comments

Castypher 13 years, 1 month ago

Hey, I did the same thing in a quiz today. What the hell.

Undeadragons 13 years, 1 month ago

Ah the joys of programming.

All the more reason for a saner programming language in my opinion.

Mega 13 years, 1 month ago

Quote:
Ah the joys of programming.

All the more reason for a saner programming language in my opinion.

A saner language? What, you mean C#, that annoying bastard child that occurred when Java snuck into

C++'s room late one night? :3

And I cannot help but laugh at the foo() function. They're STILL using that in C++ quizzes?

This kind of problem is the type of thing all programmers have to deal with in one way or another with

any dynamic object constructs in a programming language. In real situations, I don't use templates,

since I'm developing game engines that are supposed to run at +-60FPS, and the template system

creates a ton of extra overhead when using it for game-objects.

Rusky 13 years, 1 month ago

I definitely don't mean C# when I say a saner language, although some people might… I also don't understand what you mean by "they're STILL using [foo()] in C++ quizzes." Are you referring to the name? Why would "they" stop using a perfectly good metasyntactic variable?

In any case, you're completely wrong about templates. They are 100% compile-time and not dynamic in any way. The only overhead they introduce at runtime is a space overhead, if you can even consider it that. Each instantiation of a template is created at compile time and becomes exactly the same code-generation wise as if you had done it all manually.

It is also completely untrue that "all programmers have to deal with" "this kind of problem." Plenty of languages have generics without mangling scope- the only reason C++ programmers have to deal with this is the stupid C-macro/operationally thinking mindset of the standards committee. If both cases simply resolved to the scope of the template declaration things would be perfectly fine.

JoshDreamland 13 years, 1 month ago

Welcome to C++. This is C++. Welcome. This is C++, welcome to C++!

You can do anything with C++. Anything at all! The only limit is yourself.

Welcome to C++. Welcome to C++! This is C++, welcome! Yes, this is C++, and welcome to you who uses C++!

You can do anything with C++. The infinite is possible with C++.

Welcome.

Rusky 13 years, 1 month ago

Including shoot yourself in the foot with a million temporary bullets. :P

JoshDreamland 13 years, 1 month ago

Yeah, there's that. Just instantiate them during war while the shoot() method isn't overloaded to spray confetti.

sirxemic 13 years, 1 month ago

C++ shenanigans woo

Undeadragons 13 years, 1 month ago

Quote:
A saner language? What, you mean C#…
Good god no, I said saner.

Quote:
Including shoot yourself in the foot with a million temporary bullets.

Reminds me of what Bjarne Stroustrup said: "C makes it easy to shoot yourself in the foot. C++ makes it harder, but when you do, it blows away your whole leg."

Rusky 13 years, 1 month ago

Haha, love those. :)

Quote:
LISP: You shoot yourself in the appendage which holds the gun with which you shoot yourself in the appendage which holds the gun with which you shoot yourself in the appendage which holds the gun with which you shoot yourself in the appendage which holds the gun with which you shoot yourself in the appendage which holds the gun with which you shoot yourself in the appendage which holds…