tags:

views:

717

answers:

3

Guys,
[question update according to updated requirements]
I've implemented following function which should return either first not null element or throw an exception.
Also could you invent more classic and shorter name like '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;
}
+2  A: 

If the ctor for T does anything significant, it appears like you're doing it three times every time through "select_first_not_empty".

Oracle calls something similar "COALESCE", if you're looking for a better name.

I'm not sure what the point is, though. If I really wanted to know whether something was set or not, I'd use nullable pointers rather than references. "NULL" is a far better indicator of the intent to not have the variable set than to use an in-band value like 0 or "".

Paul Tomblin
It will be mostly for pointers and probably strings.
Mykola Golubyev
+2  A: 

C# has a similarly functioning built-in operator ??, which I believe is called coalesce.

Perl's || (short-circuit logical OR) operator also has similar functionality: instead of return 0 or 1, it returns the value of the first argument evaluating to true:

0 || 7

returns 7, not 1 or true as a C\C++ or C# programmer would expect.

The closest thing to this that C++ has built in is the find_if algorithm:

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));
Eclipse
I need c++ solution
Mykola Golubyev
I realize, I was just giving you pointers to try and think of a name you'd like. There is no built-in C++ version of this, and your version looks like it works.
Eclipse
I've updated the question. Please take a look again.
Mykola Golubyev
+3  A: 

you can try do next

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;
}
bb
I guess you wanted do something other in this sample code. But you've mixed some "zero value" and "default value"
bb
Could you update your answer according to updated question?
Mykola Golubyev
Where is the exception thorw?
Mykola Golubyev
oops! you edited your question again
bb
Sorry for that. I like the idea of two functions and zeroValue. The last thing to come up with is a good enough name to be the util function.
Mykola Golubyev
The "zerovcalue" would possibly confusing if you named the function coalesce (as in SQL). In SQL, the function accepts 2 or more arguments. coalesce(a,b,c)=coalesce(a,coalesce(b,c)).
MSalters