kfm*_*e04 2 c++ templates constraints stdmap c++11
我有一个类模板,打算使用其参数K作为地图的关键.
有没有办法将模板参数限制为符合std :: map中的Key的类型?
我意识到,即使没有这样的约束,编译器也会吐出一堆模板错误,比如K没有operator < (),但如果我能在指定需求时使代码更明显,那就更好了.
欢迎使用C++ 11解决方案.
template< typename K >
class Foo
{
// lots of other code here...
private:
std::map< K, size_t > m_map;
};
Run Code Online (Sandbox Code Playgroud)
这取决于你的意思"遵守".如果您想验证是否K有<操作员,那么您可以尝试Boost Concept Checking Library.
#include "boost/concept_check.hpp"
template< typename K >
class Foo
{
BOOST_CONCEPT_ASSERT((boost::LessThanComparable< K >));
// lots of other code here...
private:
std::map< K, size_t > m_map;
};
Run Code Online (Sandbox Code Playgroud)
但是,如果要验证是否<定义了StrictWeakOrdering K,则需要在所有可能的输入下测试运行时行为.
C++11版本:
\n#include <type_traits>\n\ntemplate<class T>\nstruct satisfies_key_req{\n struct nat{};\n\n template<class K> static auto test(K* k) -> decltype(*k < *k);\n template<class K> static nat test(...);\n\n static bool const value = !std::is_same<decltype(test<T>(0)), nat>::value;\n};\n\n#include <iostream>\n\nstruct foo{};\n\nint main(){\n static bool const b = satisfies_key_req<int>::value;\n std::cout << b << '\\n';\n static bool const b2 = satisfies_key_req<foo>::value;\n std::cout << b2 << '\\n';\n}\nRun Code Online (Sandbox Code Playgroud)\n输出:
\n1\n0\nRun Code Online (Sandbox Code Playgroud)\n我在这里使用的关键点是表达式 SFINAE : auto test(K* k) -> decltype(*k < *k)。如果 Trailing-return-type 中的表达式无效,则将test从重载集中删除该特定重载。换句话说,它是SFINAE'd。
\xc2\xa714.8.2 [temp.deduct]
\n\np6在模板实参推导过程中的某些时刻,需要采用使用模板实参的函数类型,并将这些模板实参替换为相应的模板实参。当任何显式指定的模板参数被替换到函数类型中时,这是在模板参数推导开始时完成的,并且当从默认参数推导或获得的任何模板参数被替换时,在模板参数推导结束时再次完成。
\np7替换发生在函数类型和模板参数声明中使用的所有类型和表达式中。这些表达式不仅包括常量表达式(例如出现在数组边界中或作为非类型模板参数的常量表达式),还包括、 和其他允许非常量表达式的上下文中的 通用表达式(即非常量表达式)。
\nsizeofdecltypep8 如果替换导致无效类型或表达式,则类型推导失败。无效类型或表达式是指如果使用替换参数编写的类型或表达式,其格式会不正确。[...]
\n
您可以在您的类中以三种方式使用它Foo来触发错误。
// static_assert, arguably the best choice\ntemplate< typename K >\nclass Foo\n{\n static_assert<satisfies_key_req<K>::value, "K does not satisfy key requirements");\n // lots of other code here...\n\n private:\n std::map< K, size_t > m_map;\n};\n\n// new-style SFINAE'd, maybe not really clear\ntemplate<\n typename K,\n typename = typename std::enable_if<\n satisfies_key_req<K>::value\n >::type\n>\nclass Foo\n{\n // lots of other code here...\n\n private:\n std::map< K, size_t > m_map;\n};\n\n// partial specialization, clarity similar to SFINAE approach\ntemplate< \n typename K,\n bool = satisfies_key_req<K>::value\n>\nclass Foo\n{\n // lots of other code here...\n\n private:\n std::map< K, size_t > m_map;\n};\n\ntemplate<typename K>\nclass Foo<K, false>;\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
412 次 |
| 最近记录: |