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

RetroX 13 years, 2 months ago

My favourite one is:

% ls
foot.c foot.h foot.o toe.c toe.o
% rm * .o
rm: .o: No such file or directory
% ls
%