8

C++0x adds pretty darn comprehensive type inference support. I'm sorely tempted to use it everywhere possible to avoid undue repetition, but I'm wondering if removing explicit type information all over the place is such a good idea. Consider this rather contrived example:

Foo.h:

#include <set>

class Foo {
private:

    static std::set<Foo*> instances;

public:

    Foo();
    ~Foo();

    // What does it return? Who cares! Just forward it!
    static decltype(instances.begin()) begin() {
        return instances.begin();
    }

    static decltype(instances.end()) end() {
        return instances.end();
    }

};

Foo.cpp:

#include <Foo.h>
#include <Bar.h>

// The type need only be specified in one location!
// But I do have to open the header to find out what it actually is.
decltype(Foo::instances) Foo::instances;

Foo() {

    // What is the type of x?
    auto x = Bar::get_something();

    // What does do_something() return?
    auto y = x.do_something(*this);

    // Well, it's convertible to bool somehow...
    if (!y) throw "a constant, old school";

    instances.insert(this);

}

~Foo() {
    instances.erase(this);
}

Would you say this is reasonable, or is it completely ridiculous? After all, especially if you're used to developing in a dynamic language, you don't really need to care all that much about the types of things, and can trust that the compiler will catch any egregious abuses of the type system. But for those of you that rely on editor support for method signatures, you're out of luck, so using this style in a library interface is probably really bad practice.

I find that writing things with all possible types implicit actually makes my code a lot easier for me to follow, because it removes nearly all of the usual clutter of C++. Your mileage may, of course, vary, and that's what I'm interested in hearing about. What are the specific advantages and disadvantages to radical use of type inference?

2
  • Actually, you do need to care about types if you're developing in a dynamic language; if you have the type of something wrong, you don't find out until you hit that section of code at run-time. Jan 7, 2011 at 19:42
  • @Larry: Of course. But not in the sense that you need to predict the exact type and inheritance chain of every object in use.
    – user7043
    Jan 7, 2011 at 22:22

3 Answers 3

5

Being mainly a Python programmer myself, I share the mindset that the programmer doesn't need to know the exact type. In the case of C++, especially when dealing with templated templated templated ... templates. Of course that's not because I despice static typing (I don't - I consider Haskell one of the best things since sliced bread, partially because of its static typing) but because I don't care about the exact type. Why, is not demonstrated well by examples that use names like foo or get_stuff(). So let's choose something closer to reality:

auto users = get_users();
vector<decltype(users[0])> blocked_users;
/* I'm not a C++ guru, much less C++0x so forgive me if type
   inference and foreach must be combined differently */
for (auto user : users) {
    if (check_name(user.name)) blocked_users.push_back(user)
}

Not a single type annotation, but it's perfectly clear what it does, right? This code doesn't care what's the type of users, it just need some range to iterate over which contains things with a name that can be fed to check_name. Nothing more. Nobody cares about the 100-ish characters of type names you'd have to type otherwise.

Same applies to most code with meaningful names. The example in the question is not clear, but it wouldn't be clear with explicit type names either, because neither context nor identifiers give any indication of what's going on. Use meaningful identifiers, and the code can be understood regardless of explicit type annotations.

0
3

The reason they brought in inference was to prevent people from writing code like:

foo().bar().baz().etc();

When you could write:

Foo f = foo();
Bar b = f.bar();
...

Except Foo would be some long templated type, so it becomes nicer to write:

auto f = foo();
auto b = f.bar();
...

So, as a rule of thumb, if using auto causes you to write code as above instead of code similar to the first example then by all means use it. Otherwise, stick to adding explicit definitions.

2
  • Makes sense. I do find myself using auto in a lot of cases where I'm sure others would be explicit, but I don't see what's really wrong with, say, auto f = new SomethingLong(), because it's obvious what the expression returns. I'm just wondering where to draw the line.
    – Jon Purdy
    Jan 7, 2011 at 8:18
  • That's fine if SomethingLong isn't part of any inheritance structure, but unless you're sure that it never will be then I'd advise against it. It's much easier to draw the line on the cautious side. Jan 7, 2011 at 8:22
2

There are good reasons for not always using type inference. Haskell has type inference, but I usually declare function types explicitly anyway. That is partially a result of my development style. I declare the function first:

myFunction :: [Int] -> Int
myFunction xs = undefined
Next, I'll write the code that uses that function and do a compile to make sure it type checks. Once it type checks, I'll go ahead with the implementation.

The other reason for declaring function types is that the declarations can serve as additional documentation. That this documentation is verified on every compile is a bonus.

1
  • 2
    While the type-first approach is very elegant in Haskell, I doubt that it's suitable for C++. Without concepts, a C++ template signature basically says nothing - it's the implementation that defines the requirements types and arguments have to meet. Templates just do duck typing at compile time - "try and look if it works". Thus I'd say, we can rather be implicit with the types just as dynamic duck-typed languages are too.
    – Dario
    Jan 8, 2011 at 12:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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