采用模板的模板参数(嵌套模板)

时间:2016-05-11 17:12:24

标签: c++ templates template-templates

我正在努力避免代码重复,因为以下内容:

template<class StringType, typename type1, typename type2, class MapType>
void readDatastructure(MapType<type1, type2> map, const StringType path) {
... some code
}

我有几种不同的地图类型,它们具有不同的type1type2参数。在某些时候,我想静态检查哪些类型是type1type2,我无法弄清楚如何编译这个东西。我在该模板声明中尝试了几种变体,但它们似乎都没有效果。这甚至可能吗?

干杯,

3 个答案:

答案 0 :(得分:3)

你想要的东西是

template<class StringType, typename type1, typename type2,
         template<class, class> class MapType>
void readDatastructure(MapType<type1, type2> map, const StringType path);

但这不适用于std::map,它有两个额外的模板参数(用于比较器和分配器)。所以你要么必须要做

template<class StringType, typename type1, typename type2,
         template<class...> class MapType>
void readDatastructure(MapType<type1, type2> map, const StringType path);

或添加额外的模板参数,即

template<class StringType, typename type1, typename type2, class C, class A,
         template<class, class, class, class> class MapType>
void readDatastructure(MapType<type1, type2, C, A> map, const StringType path);

第一个仍然无法使用非std::map非默认比较器/分配器;如果您的地图不具有恰好四个模板类型参数,则第二个不起作用 - 例如unordered_map,有五个。

因此,让地图类型发布这些类型可能会更好。例如,std::map将其发布为key_typemapped_type。通过“发布”,我的意思是将它们定义为成员typedef。然后你可以写

template<class StringType, class MapType>
void readDatastructure(MapType map, const StringType path);

并使用例如typename MapType::key_type代替type1

如果您无法更改地图类型,并且它们不遵循标准协议,您可以编写特征类并将其专门用于地图类型:

template<class T>
struct map_traits {
    using key_type = typename T::key_type;
    using mapped_type = typename T::mapped_type;
};
template<class T1, class T2>
struct map_traits<MyBrokenMap<T1, T2>> {
    using key_type = T1;
    using mapped_type = T2;
};

然后你可以使用typename map_traits<MapType>::key_type等。

答案 1 :(得分:1)

模板模板参数

//  POST -- PARSE / PROCESSING
if (!empty($_POST)):
    $rjw_file = $_FILES["rjw_settings"]["name"]["rjw_file_src"] or die();
endif;

function rjw_settings_section_callback(  ) {
    global $rjw_file;
    //  Display text if WooCommerce is disabled.
    if ( !in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', get_option( 'active_plugins'))))
        echo "Please Activate WooCommerce";

    print_r($_POST);
    echo ("<br/><br/><br/>");
    print_r($_FILES);
    echo("<br/><br/><br/>");
    print_r($rjw_file);
}

答案 2 :(得分:1)

所有std :: map类型定义类型key_typemapped_type

编写一个is_map特征来约束模板函数扩展是很简单的。

示例:

#include <iostream>
#include <map>
#include <unordered_map>
#include <utility>
#include <typeinfo>


template<class Map> struct is_map
{
    static constexpr bool value = false;
};

template<class K, class V, class Comp, class Alloc>
struct is_map<std::map<K, V, Comp, Alloc>>
{
    static constexpr bool value = true;
};

template<class K, class V, class Comp, class Hash, class Alloc>
struct is_map<std::unordered_map<K, V, Comp, Hash, Alloc>>
{
    static constexpr bool value = true;
};

template<
class Map,
class String,
std::enable_if_t<is_map<Map>::value>* = nullptr
>
void readDataStructure(Map& map, String&& path)
{
    std::cout << "reading map with key type: " << typeid(typename Map::key_type).name() << std::endl;
    std::cout << "      and with value type: " << typeid(typename Map::mapped_type).name() << std::endl;
    std::cout << "--------------------------"  << std::endl;
}


int main()
{
    std::map<int, std::string> m1;
    std::unordered_map<int, std::wstring> m2;
    readDataStructure(m1, "foo.txt");
    readDataStructure(m2, "foo.txt");
}

示例输出:

reading map with key type: i
      and with value type: NSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE
--------------------------
reading map with key type: i
      and with value type: NSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEE
--------------------------