【问题标题】:C++ macro for string literal begin iterator and end iterator字符串文字开始迭代器和结束迭代器的 C++ 宏
【发布时间】:2012-09-19 00:00:53
【问题描述】:

我想要一个这样的宏

STR_ITERATORS("My string")

产生

 pBegin, pEnd

例如,您可以使用它来搜索矢量...

std::vector<char> str1;

std::search(str1.begin(), str1.end(), STR_ITERATORS("寻找这个"));

请注意,搜索需要两对迭代器,宏提供第二对。

宏可以写两次——一次用于普通字符,一次用于宽字符。不必一次性解决所有问题。

注意:我没有使用最新编译器的选项。 (这让它有点无聊不是吗?:-)

【问题讨论】:

  • 这只是为了节省按键吗?为什么不直接创建一个 search_for_string() 辅助函数?
  • @bluedog: 当然可以,但是宏在 C++ 中不受欢迎,原因有以下几个:1) 编写 非常困难不可能 >健壮 宏,取决于上下文,2) 没有类型安全保证,3) 不尊重范围或命名空间规则,4) 几乎总是有更好的解决方案,例如模板和函数。
  • 再展示一个例子,让您提出的设计可行。您应该询问您实际面临的现实生活中的问题。您提出的设计不如使用内联辅助函数。

标签: c++ string stl macros


【解决方案1】:

在 C++11 中,为此创建自己的搜索函数很容易。

template<class iter1, class iter2>
iter1 search(iter1 stackbegin, iter1 stackend, iter2 needlebegin, iter2 needleend)
{return std::search(stackbegin, stackend, needlebegin, needleend);}

template<class iter1, class needlecontainer>
iter1 search(iter1 stackbegin, iter1 stackend, const needlecontainer& needle)
{return std::search(stackbegin, stackend, std::begin(needle), std::end(needle));}

template<class stackcontainer, class needlecontainer>
decltype(std::begin(std::declval<stackcontainer>()))
search(const stackcontainer& stack, const needlecontainer& needle)
{return std::search(std::begin(stack), std::end(stack), std::begin(needle), std::end(needle));}

template<class stackcontainer, class needlecontainer>
decltype(std::begin(std::declval<stackcontainer>()))
search(stackcontainer& stack, const needlecontainer& needle)
{return std::search(std::begin(stack), std::end(stack), std::begin(needle), std::end(needle));}

并使用它们:

int main() {
    std::vector<char> str1;
    auto it = search(str1, "Look for this");
}

编译证明:http://ideone.com/cO1rz(这个版本的 gcc 没有 std::beginstd::end,所以我必须自己定义它们)和 C++03 版本:http://ideone.com/gt1Do

如果您真的很想要一个简短的宏,并且您可以保证文字共享相同的空间:

template<int N>
const char* end(const char(&s)[N]) {return s+N;}
#define STR_ITERATORS(X) X, end(X) //BE WARNED, HIGHLY UNSAFE, NOT PORTABLE

【讨论】:

  • 这看起来不错,但不幸的是我的项目跨越了许多平台,并且一些编译器稍旧(但不是太旧)。
  • @bluedog:这是一个即使在较旧的编译器中也能编译的版本:ideone.com/gt1Do
  • 似乎是一个很好的答案,但我希望有一个更紧凑、更神奇的解决方案。
  • @bluedog:由于不保证字符串文字彼此相同,这将是最安全和最紧凑的便携解决方案。我可以制作一个宏版本,但它会是 more 代码,而不是更少。它也会不太安全。或者您可以忽略可移植性,并在 Visual Studio 中轻松完成。
  • 只是尺寸令人反感。我对模板没有意见,我同意这里的每个人的观点,即宏并不理想。我想我只是想知道是否有一个非常短的解决方案可以将字符串文字与 STL 混合。
【解决方案2】:

boost range 提供了使用范围的算法重载,并将自动处理大多数类似 STL 的集合。具体来说,字符串也可以自动转换为范围。还有免费的函数开始和结束。

【讨论】:

  • 这是迄今为止我最喜欢的答案,因为它通常最有用。不幸的是,我无法在这个项目上使用 boost。
【解决方案3】:
template<int N>
int GetLengthOfLiteral(const wchar_t (&literal)[N]) { return N - 1; }

template<int N>
int GetLengthOfLiteral(const char (&literal)[N]) { return N - 1; }

#define LITERAL_ITERATORS(literal) (literal), ((literal) + GetLengthOfLiteral(literal)

【讨论】:

  • 是否保证两个包含相同字符的不同字符串字面量是同一个对象?
  • 哪两种不同的字符串文字?
  • LITERAL_ITERATORS("x") 将扩展为 ("x"), (("x") + GetLengthOfLiteral("x"))。替换中有三个不同的"x"。能保证这三个都是同一个对象吗?
  • 糟糕,是的,我忘记了。
猜你喜欢
  • 2011-07-22
  • 1970-01-01
  • 2021-09-20
  • 2011-01-23
  • 1970-01-01
  • 2012-10-23
  • 2015-07-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多