std::字符串与模板一起使用,请检查是否为空

std::string used with template, check if empty

本文关键字:检查 是否 字符串 一起 std      更新时间:2023-10-16

我想使用一个函数,该函数接受类型为T的通用参数,并在函数中检查传入的变量是否为NULL。我可以简单地用这样的原始类型来做:

if (var) doSomething();

然而,为了检查它是否是std::string,我需要做:

if (!var.empty()) doSomething();

检查传入的参数是否为NULL的最佳、最通用的方法是什么?我想使用所有的基元类型和std::string。也许我可以用typeid

首先,如果你使用了正确的术语,研究这个主题会更好。空字符串不是"NULL";零等价整数也不是"NULL"。唯一可以成为"NULL"的是一个指针(尽管我们现在使用nullptr)。所以我们可以立即停止使用这个术语。

对于任意类型,没有通用的"未设置"值,因此也没有常见的方法来检测这种情况。但是,您可以使用明确添加这种可能性的包装器类型,例如boost::optional<T>:

#include <boost/optional.hpp>
#include <iostream>
template <typename T>
void foo(boost::optional<T> arg)
{
   if (arg)
      std::cout << arg.get() << 'n';
}
int main()
{
    boost::optional<int>   a{123};
    boost::optional<int>   b{boost::none};
    boost::optional<float> c{boost::none};
    boost::optional<float> d{123.456};
    foo(a);
    foo(b);
    foo(c);
    foo(d);
    // Or, pass it directly:
    foo(boost::optional<std::string>{"abc"});
    foo(boost::optional<std::string>{boost::none});
    foo(boost::optional<std::string>{});  // as if boost::none were given
}
// $ g++ -std=c++14 -O2 -Wall -Wextra -pedantic -pthread main.cpp && ./a.out
// 123
// 123.456
// abc

(现场演示)

您唯一的其他选择是接受指向对象的指针,并检查指针上的NULL ity。但这是一个抽象泄漏,因为接受指针表示的是该函数以外的意图;在清晰的所有权语义方面,它也造成了一些混乱。

通过使用一个与对象的默认构造版本相比的模板,您可以在不重复自己的情况下获得通用代码:

#include <iostream>
#include <string>
template <typename T>
void doSomething(T t)
{
    std::cout << "Doing something with " << t << " n";
}
void doSomethingElse()
{
    std::cout << "Doing something elsen";
}
template <typename T>
void f(T t)
{
    if (t!=T{}) doSomething(t); // compare with default constructed object
    else doSomethingElse();
}
int main()
{
    int var1{};
    std::string var2{};
    int var3{3};
    std::string var4{"var4's text"};
    f(var1);
    f(var2);
    f(var3);
    f(var4);
}

产品:

Doing something else
Doing something else
Doing something with 3
Doing something with var4's text