C ++ выберите первый не нулевой элемент - PullRequest
1 голос
/ 10 марта 2009


[обновление вопроса в соответствии с обновленными требованиями]
Я реализовал следующую функцию, которая должна возвращать либо первый не нулевой элемент, либо выдавать исключение.
Также не могли бы вы придумать более классические и более короткие названия, такие как «max», «min», «pair»?

template <typename T>
T select_first_not_empty( const T& a, const T&b )
{
    static T null = T();

    if ( a == null && b == null )
        throw std::runtime_error( "null" );

    return
        a != null ? a : b;
}

int main()
{
    const int a1 = 2;
    const int b1 = 0;

    const int* a2 = 0;
    const int* b2 = new int(5);

    const std::string a3 = "";
    const std::string b3 = "";

    std::cout << select_first_not_empty( a1, b1 ) << std::endl;
    std::cout << select_first_not_empty( a2, b2 ) << std::endl;
    std::cout << select_first_not_empty( a3, b3 ) << std::endl;

    return 0;
}

Ответы [ 3 ]

3 голосов
/ 10 марта 2009

можно попробовать сделать дальше

template < typename T >
T get_valuable( const T& firstValue, 
                const T& alternateValue, 
                const T& zerroValue = T() )
{
    return firstValue != zerroValue ? firstValue : alternateValue;
}

// usage
char *str = "Something"; // sometimes can be NULL
std::string str2 ( get_valuable( str,  "" ) );

// your function
template <typename T>
T select_first_not_empty( const T& a, 
                          const T& b, 
                          const T& zerroValue = T() )
{
    const T result = get_valuable( a, b, zerroValue );
    if ( result == zerroValue )
    {
        throw std::runtime_error( "null" );
    }
    return result;
}
2 голосов
/ 10 марта 2009

C # имеет аналогично функционирующий встроенный оператор ??, который, я считаю, называется coalesce.

Оператор Perl || (логическое ИЛИ короткого замыкания) также имеет аналогичную функциональность: вместо возврата 0 или 1 он возвращает значение первого аргумента, оцениваемое как true:

0 || 7

возвращает 7, а не 1 или true, как ожидал бы программист C \ C ++ или C #.

Самым близким к этому встроенным в C ++ является алгоритм find_if:

vector<int> vec;
vec.push_back(0);
vec.push_back(0);
vec.push_back(7);

vector<int>::iterator first_non_0 = 
    find_if(vec.begin(), vec.end(), bind2nd(not_equal_to<int>(), 0));
2 голосов
/ 10 марта 2009

Если ctor для T делает что-то существенное, похоже, что вы делаете это три раза каждый раз через «select_first_not_empty».

Oracle называет что-то похожее "COALESCE", если вы ищете лучшее имя.

Я не уверен, в чем суть. Если бы я действительно хотел знать, было ли что-то установлено или нет, я бы использовал указатели, которые можно обнулять, а не ссылки. «NULL» является гораздо лучшим индикатором намерения не устанавливать переменную, чем использовать внутриполосное значение, например 0 или «».

...