One way you can accomplish this is by calling the
setreg() function. You can also use the
getline() function to get the contents of the current line, which is also convenient since it doesn't include the final newline.
For the specific case of yanking the current line:
call setreg('+', getline('.'))
And you can create a mapping for it with:
nnoremap <silent> <C-y> :call setreg('+', getline('.'))<CR>
Using the function call will not affect your cursor position in any way.
UPDATE: You can extend this definition to take a count (to work with
3<C-y> by passing
getline() a second argument with the ending line, and using
v:count1 to figure out the end line from the count.
UPDATE 2: We pass a second argument of
setreg() to force characterwise mode, which means Vim will not add a final newline, even when multiple lines are yanked with a count.
nnoremap <silent> <C-y> :<C-u>call setreg('+',
\ getline('.', line('.') + v:count1 - 1), 'v')<CR>
Perhaps it makes sense to create an analogous mapping for Visual mode (and Select mode). The one for Visual mode doesn't preserve the cursor position (since it drops the Visual selection), but it might still be useful in cases where you want to copy lines to the
"+ register without having to count them.
I went with a definition that will always copy lines, even if the Visual selection is characterwise or blockwise. In a way that's convenient to implement using the same
getline() combo, but it might also be a reasonable way to define it anyways.
vnoremap <silent> <C-y> :<C-u>call setreg('+',
\ getline("'<", "'>"), 'v')<CR>gV