模板类

时间:2015-10-08 13:36:11

标签: c++ templates c++11 boost associative-array

我已经定义了很多这样的模板类变量:

someTemplate<int, int, char> variable1;
someTemplate<char, int, char> variable2;
someTemplate<double, double, int> variable3;
someTemplate<int, int, char> variable4;
someTemplate<int, int, float> variable15;
...

现在,我想定义关联std :: map,但我不知道如何编写类型签名(声明)......如果它甚至可能。例如:

std::map<int,_____> assocArr;

我需要它,因为我想使用循环调用std :: map的所有项目的函数:

for(auto item : assocArr)
{
    if(item.first == integerVar)
        item.second->myFunction();
}

我知道,这个简单的解决方案是make class,它封装了所有模板类,但我的问题是如果没有这个类就可以做到这一点? 由于模板类的许多变体,boost :: variant的使用是有问题的。

2 个答案:

答案 0 :(得分:2)

添加Boost Type Erasure路线。

BOOST_TYPE_ERASURE_MEMBER((has_myFunction), myFunction, 0)

namespace bte = boost::type_erasure;
using Erased = bte::any<
    boost::mpl::vector<
        bte::copy_constructible<>,
        has_myFunction<void(), bte::_self const>, 
        bte::relaxed 
    > >;

这有一点学习曲线¹,但如果你有更多的概念可以满足,这可能是一个非常好的权衡。

该示例还展示了如何实现地图值的值语义(假设someTemplate<>是可复制构造的。)

样本

<强> Live On Coliru

#include <map>
#include <iostream>
#include <boost/type_erasure/any.hpp>
#include <boost/type_erasure/member.hpp>
#include <boost/type_erasure/constructible.hpp>

BOOST_TYPE_ERASURE_MEMBER((has_myFunction), myFunction, 0)

namespace bte = boost::type_erasure;
using Erased = bte::any<
    boost::mpl::vector<
        bte::copy_constructible<>,
        has_myFunction<void(), bte::_self const>, 
        bte::relaxed 
    > >;

template <typename T, typename U, typename V>
struct someTemplate {
    void myFunction() const {
        std::cout << __PRETTY_FUNCTION__ << "\n";
    }
};

int main() {
    std::map<int, Erased> assocArr {
        { 1,  someTemplate<int,    int,    char>  {} },
        { 2,  someTemplate<char,   int,    char>  {} },
        { 3,  someTemplate<double, double, int>   {} },
        { 4,  someTemplate<int,    int,    char>  {} },
        { 5,  someTemplate<int,    int,    float> {} },
    };

    for(auto& item : assocArr)
        //if(item.first == integerVar)
    {
        std::cout << "id: " << item.first << " ";
        item.second.myFunction();
    }
}

印刷:

id: 1 void someTemplate<T, U, V>::myFunction() const [with T = int; U = int; V = char]
id: 2 void someTemplate<T, U, V>::myFunction() const [with T = char; U = int; V = char]
id: 3 void someTemplate<T, U, V>::myFunction() const [with T = double; U = double; V = int]
id: 4 void someTemplate<T, U, V>::myFunction() const [with T = int; U = int; V = char]
id: 5 void someTemplate<T, U, V>::myFunction() const [with T = int; U = int; V = float]

¹,直播确实证明:)

答案 1 :(得分:1)

您可以使用Boost Type Erasure或制作自己的自定义类型擦除包装。

是的,这意味着存储一个包装器,但这就是你需要的。因为地图不能包含“任何随机类型”,并且使用例如如果“模板类的许多变体”,则extension String { func getRegexVariableNamed(name: String, forRegexString regexString: String) -> String? { /** ... **/ return "TO BE IMPLEMENTED".lowercaseString // Using lowercase to prevent the compiler from inlining } } class XYZ { func extractInformation(info1: AutoreleasingUnsafeMutablePointer<NSString?>, info2: AutoreleasingUnsafeMutablePointer<NSString?>, info3: AutoreleasingUnsafeMutablePointer<NSString?>, info4: AutoreleasingUnsafeMutablePointer<NSString?>, fromSource source: String) -> Bool { guard let vp = source.getRegexVariableNamed("ID", forRegexString: "vp=(?P<ID>\\d+)") else { return false } info4.memory = vp info1.memory = "ABC" info2.memory = "DEF" info3.memory = "GHI" + vp return true } } // Code in playground let obj = XYZ() var info1: NSString? var info2: NSString? var info3: NSString? var info4: NSString? if !obj.extractInformation(&info1, info2: &info2, info3: &info3, info4: &info4, fromSource: "") { print("NO") }else{ print("YES") info1 // "ABC" info2 // "DEF" info3 // "GHIto be implemented" info4 // "to be implemented" } 将无效。

粗略草图:WIP https://www.livecoding.tv/sehe/

<强> Live On Coliru

boost::any

打印

#include <map>
#include <iostream>
#include <memory>

template <typename T, typename U, typename V>
struct someTemplate {
    void myFunction() const {
        std::cout << __PRETTY_FUNCTION__ << "\n";
    }
};

struct someErasure {
    template <typename... Ts> /*explicit*/ someErasure(someTemplate<Ts...> const& v) 
        : _holder(new holder<someTemplate<Ts...> >(&v))
    { }

    someErasure(someErasure const& rhs) : _holder(rhs._holder->clone()) { }

    void myFunction() const {
        _holder->myFunction();
    }

  private:
    struct itf {
        virtual void myFunction() const = 0;
        virtual itf* clone() const = 0;
    };

    template <typename T> struct holder : itf {
        holder(T const* v) : _v(v) { }
        T const* _v;

        virtual void myFunction() const {
            _v->myFunction();
        }

        virtual holder* clone() const { return new holder(_v); }
    };

    std::unique_ptr<itf> _holder;
};

int main() {
    someTemplate<int,    int,    char>  variable1;
    someTemplate<char,   int,    char>  variable2;
    someTemplate<double, double, int>   variable3;
    someTemplate<int,    int,    char>  variable4;
    someTemplate<int,    int,    float> variable5;

    std::map<int, someErasure> assocArr {
        { 1,  variable1 },
        { 2,  variable2 },
        { 3, variable3 },
        { 4,  variable4 },
        { 5,  variable5 },
    };

    for(auto& item : assocArr)
        //if(item.first == integerVar)
    {
        std::cout << "id: " << item.first << " ";
        item.second.myFunction();
    }
}