我已经定义了很多这样的模板类变量:
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的使用是有问题的。
答案 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();
}
}