为什么不在这里考虑std :: begin / end?

时间:2016-10-20 21:28:22

标签: c++ templates iterator enable-if

我有一个模板免费功能算法"包含":

template <typename collection_type, typename element_type, typename comparison_function_type>
bool contains(const collection_type & collection, const element_type & element, comparison_function_type comparison_function)
{
    using namespace ::std;
    return end(collection) != find_if(begin(collection), end(collection), [&](const element_type & candidate) { return comparison_function(candidate, element); });
}

这适用于以下内容或以下内容失败,具体取决于范围:

        static const TCHAR * kPackFiles[] = { _T("boxit"), _T("pack") };
        const auto & name = filename.GetName();
        if (contains(kPackFiles, name, Toolbox::case_insensitive_equal_to<Toolbox::TCHARStringPolicy>()))
              do_something_interesting();

以上编译除非以下内容在此范围内:

template <typename T>
const typename ::std::enable_if<::std::is_same<T, CStringA>::value || ::std::is_same<T, CStringW>::value, T>::type::XCHAR *
    begin(const T & str) { return str.GetString(); }

template <typename T>
const typename ::std::enable_if<::std::is_same<T, CStringA>::value || ::std::is_same<T, CStringW>::value, T>::type::XCHAR *
    end(const T & str) { return str.GetString() + str.GetLength(); }

以上内容旨在扩展CStringA和CStringW,以便为它们提供const char_type迭代器。这通常适用于其他方案,例如for (c : my_cstring) cout << c;

但对于上述情况 - collection_type=const TCHAR *[2]我从编译器获得的消息是它无法专门化函数模板&amp;仅列出上面找到的专业。

这里有确切的信息:

error C2893: Failed to specialize function template 'const ::std::enable_if<std::is_same<T,CStringA>::value||std::is_same<T,CStringW>::value,T>::type::XCHAR *Toolbox::end(const T &)'

而且我猜测我在这里遇到了一些命名空间规则。

我正在将自定义库代码移动到namespace Toolbox - 包括contains模板和begin以及end用于CStringA / W. / p>

我已经验证过,如果我只是不定义上述代码编译的我的CString版本的begin / end。因此,原始数组的开始/结束的必要定义包括&amp;可见。

但我不知道为什么我的Toolbox::contains模板在这种情况下不会考虑std::begin/end - 而是试图为{{Toolbox::begin(const CString &)生成kPackFiles 1}}?

1 个答案:

答案 0 :(得分:2)

using-directive 的工作方式是([namespace.udir]/2):

  

using-directive 指定指定命名空间中的名称   可以在 using-directive 之后出现的范围内使用    using-directive 。在不合格的名称查找期间   ([basic.lookup.unqual]),名称显示为声明它们   包含两者的最近的封闭命名空间    using-directive 和指定的命名空间。 [注意:在此背景下,   “包含”表示“直接或间接包含”。 - 结束记录]

为此,{p> using namespace ::std;使::std的成员可见,就好像它们是全局命名空间的成员一样。因此,根据正常的非限定查找规则,它们被命名空间Toolbox中具有相同名称的任何内容隐藏。