Na função std :: abs

É ostd::abs() função bem definida para todos os tipos aritméticos em C ++ 11 e retornará|x| sem problema de aproximação?

Uma coisa estranha é que com o g ++ 4.7,std::abs(char), std::abs(short int), std::abs(int), std::abs(long int) estd::abs(long long int) parece retornar um duplo (ao contrário de:http://en.cppreference.com/w/cpp/numeric/math/abs). E se o número for convertido em double, poderemos ter algum erro de aproximação para um número muito grande (como-9223372036854775806LL = 2^63-3).

Então eu tenho a garantia de questd::abs(x) sempre retornará|x| para todos os tipos aritméticos?

EDIT: aqui está um programa de exemplo para fazer alguns testes

#include <iostream>
#include <iomanip>
#include <cmath>
#include <typeinfo>

template<typename T>
void abstest(T x)
{
    static const unsigned int width = 16;
    const T val = x;
    if (sizeof(val) == 1) {
        std::cout<<std::setw(width)<<static_cast<int>(val)<<" ";
        std::cout<<std::setw(width)<<static_cast<int>(std::abs(val))<<" ";
    } else {
        std::cout<<std::setw(width)<<val<<" ";
        std::cout<<std::setw(width)<<static_cast<T>(std::abs(val))<<" ";
    }
    std::cout<<std::setw(width)<<sizeof(val)<<" ";
    std::cout<<std::setw(width)<<sizeof(std::abs(val))<<" ";
    std::cout<<std::setw(width)<<typeid(val).name()<<" ";
    std::cout<<std::setw(width)<<typeid(std::abs(val)).name()<<std::endl;
}

int main()
{
    double ref = -100000000000;
    abstest<char>(ref);
    abstest<short int>(ref);
    abstest<int>(ref);
    abstest<long int>(ref);
    abstest<long long int>(ref);
    abstest<signed char>(ref);
    abstest<signed short int>(ref);
    abstest<signed int>(ref);
    abstest<signed long int>(ref);
    abstest<signed long long int>(ref);
    abstest<unsigned char>(ref);
    abstest<unsigned short int>(ref);
    abstest<unsigned int>(ref);
    abstest<unsigned long int>(ref);
    abstest<unsigned long long int>(ref);
    abstest<float>(ref);
    abstest<double>(ref);
    abstest<long double>(ref);
    return 0;
}

questionAnswers(4)

yourAnswerToTheQuestion