This is sort of both an answer and a question. I realize this thread is dead, but it exactly what I was looking into tonight.
I did some poking around and the closest thing I can get to what I want (which is similar to what you want... I have been working with pics and have no need to use c++, but I am curious how it might be done) is the first code example:
#include <iostream>
using namespace std;
extern "C" 
{
    typedef struct stuff
    {
        int x;
        double y;
    } things;
}
int main()
{
    things jmcd = { jmcd.x = 12, jmcd.y = 10.1234 };
    cout << jmcd.x << " " << jmcd.y << endl;
    return 0;
}
This has a very similar appearance to the C99 style designated initializers with a caveat I will mention later. (You would probably wrap this in #ifdef __cplusplus if you wanted the struct to be compiled by either.) The second version of code I looked at is this:
#include <iostream>
using namespace std;
extern "C" 
{
    typedef struct stuff
    {
        int x;
        double y;
    } things;
}
int main()
{
    things jmcd;
    jmcd.x = 12;
    jmcd.y = 10.1234;
    cout << jmcd.x << " " << jmcd.y << endl;
    return 0;
}
Basically, from looking at the disassembly, it appears the first example is actually slower. I have looked at the assembly output and, well, I must be a little rusty. Maybe someone could give me some insight. The assembly output of the first cpp compiled and looked like:
main:
.LFB957:
    .cfi_startproc
    .cfi_personality 0x0,__gxx_personality_v0
    pushl   %ebp
    .cfi_def_cfa_offset 8
    movl    %esp, %ebp
    .cfi_offset 5, -8
    .cfi_def_cfa_register 5
    subl    $24, %esp
    movl    $0, 12(%esp)
    movl    $0, 16(%esp)
    movl    $0, 20(%esp)
    movl    $12, 12(%esp)
    movl    12(%esp), %eax
    movl    %eax, 12(%esp)
    fldl    .LC0
    fstpl   16(%esp)
    fldl    16(%esp)
    fstpl   16(%esp)
    movl    12(%esp), %eax
    movl    %eax, 4(%esp)
    fildl   4(%esp)
    fldl    16(%esp)
    faddp   %st, %st(1)
    fnstcw  2(%esp)
    movzwl  2(%esp), %eax
    movb    $12, %ah
    movw    %ax, (%esp)
    fldcw   (%esp)
    fistpl  4(%esp)
    fldcw   2(%esp)
    movl    4(%esp), %eax
    leave
    ret
    .cfi_endproc
The second example looked like:
main:
.LFB957:
    .cfi_startproc
    .cfi_personality 0x0,__gxx_personality_v0
    pushl   %ebp
    .cfi_def_cfa_offset 8
    movl    %esp, %ebp
    .cfi_offset 5, -8
    .cfi_def_cfa_register 5
    subl    $24, %esp
    movl    $12, 12(%esp)
    fldl    .LC0
    fstpl   16(%esp)
    movl    12(%esp), %eax
    movl    %eax, 4(%esp)
    fildl   4(%esp)
    fldl    16(%esp)
    faddp   %st, %st(1)
    fnstcw  2(%esp)
    movzwl  2(%esp), %eax
    movb    $12, %ah
    movw    %ax, (%esp)
    fldcw   (%esp)
    fistpl  4(%esp)
    fldcw   2(%esp)
    movl    4(%esp), %eax
    leave
    ret
    .cfi_endproc
Both of these were generated with a g++ -O0 -S main.cpp command. Clearly, the intuitively less efficient example generated more efficient opcode in terms of number of instructions. On the other hand, there are few cases where I could imagine the few instructions being critical. (On the other hand, I really have trouble understanding assembly not written by humans, so maybe I am missing something... ) I think this provides a solution, albeit late, to the question James asked. The next thing I should test is if the same initialization is allowed in C99; if that works, I think it fully addresses James's problem. 
Disclaimer: I have no idea if this works or behaves similarly for any other compilers other than g++.