C++ 选择第一个非空元素

发布于 2024-07-14 18:35:50 字数 809 浏览 6 评论 0原文


[问题根据更新的要求更新]
我已经实现了以下函数,它应该返回第一个非空元素或抛出异常。
你还能发明更经典、更短的名字,比如“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;
}

[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;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

在风中等你 2024-07-21 18:35:50

你可以尝试下一步

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;
}

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;
}
当梦初醒 2024-07-21 18:35:50

如果 T 的 ctor 做了任何重要的事情,那么看起来您每次都通过“select_first_not_empty”执行了三次。

如果您正在寻找更好的名称,Oracle 会调用类似的“COALESCE” 。

但我不确定重点是什么。 如果我真的想知道某些内容是否已设置,我会使用可为空的指针而不是引用。 与使用带内值(如 0 或“”)相比,“NULL”更能表明不设置变量的意图。

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 "".

谈下烟灰 2024-07-21 18:35:50

C# 有一个类似功能的内置运算符 ??,我认为它称为合并。

Perl 的 || (短路逻辑 OR)运算符也具有类似的功能:它返回第一个参数的值,而不是返回 0 或 1:

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));

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));
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文