An Intro to CS course in C++ for CS majors: laying a solid low-level foundation or simple tools and algorithmic thinking? Consider the following two competing incentives in teaching a first Intro to CS course for CS majors. In my case, the course must use C++ -- that's a given.

The first incentive is that the course needs to provide a solid foundation, which includes understanding how things work under the hood and implies teaching pointer, raw array and string, dynamic allocation etc.

The second incentive is the focus on developing algorithmic thinking and taste for elegant code. This incentive seems to be served best by teaching the smallest and the simplest-to-use possible subset of the language sufficient to solve algorithmic problems, gradually getting to the level of problems used in informatics olympiads for high school. So, for example, std::vector would be taught instead of raw array and pointers would not be mentioned. This would probably also mean excluding the need to handle errors in the exercises, so as to not spoil the taste of writing short and elegant code.

Which approach is preferred? Or maybe a third approach?

Clarifications following the reply by @Ben I.

I am presenting this as a choice between two approaches, because I believe that the two approaches are in conflict. Low-level features of the language are complicated. To help students understand them, one needs to give a lot of technical examples and exercises. This totally takes the focus away from algorithmic thinking.

Also, I am writing under the assumption that, once I am convinced about the correct way of teaching, I can try to convince my colleagues to consider changes in the follow-up courses as well. Right now the curriculum is built on the first approach. The big picture that I see is that there are many CS graduates who know programming languages, but few who are good programmers. Look at the questions at leetcode.com. Almost all of them are about algorithmic thinking, because employers are looking for good programmers.
You wrote:


  The first incentive is that the course needs to provide a solid foundation, which includes understanding how things work under the hood and implies teaching pointer, raw array and string, dynamic allocation etc.


This is not the only definition of a "solid foundation".  I would suggest that your second approach is also a "solid foundation", but towards a different goal.

You could make a wonderful course out of low-level computer workings, and your students could learn a tremendous amount.  Your "second incentive" is higher-level, and you could make a wonderful course out of this as well.  

In truth, I am not sure that your goals are entirely opposed to one another.  You can teach high-level thinking and still mention what is going on under the hood, and you can teach good coding style in a low-level language.  No matter which basic approach you take, you really should make an effort to help students see at least a bit of the other side.

But in answer to your question about a basic initial approach, I might suggest the following: we often think about introductory courses as preparing us for our long-term futures, but I would argue that on a far more practical level, course 101 lays the foundation for 102, 103, 201, 202, 303, and so forth.  You are setting the stage for future learning.  Therefore, the best (introductory) course is the one that helps the students get the most learning out of their later, more advanced courses.  After all, those courses are where the rubber will really meet the road.  

So, what will set them up for success as they proceed through your entire program?  Have a few conversations with your colleagues, and take a careful look at your program's course catalog.  The answer may become fairly obvious.