今天,我编写了一些代码,需要根据模板参数的类型向不同的容器变量添加元素。我通过编写一个专门用于自己的模板参数的朋友助手类来解决它,该模板参数具有原始类的成员变量。它为我节省了几百行重复自己而没有增加太多复杂性。然而,它看起来像kludgey。我想知道是否有更好,更优雅的方式。
以下代码是一个极为简化的示例,说明了问题和我的解决方案。它用g ++编译。
#include <vector>
#include <algorithm>
#include <iostream>
namespace myNS{
template<class Elt>
struct Container{
std::vector<Elt> contents;
template<class Iter>
void set(Iter begin, Iter end){
contents.erase(contents.begin(), contents.end());
std::copy(begin, end, back_inserter(contents));
}
};
struct User;
namespace WkNS{
template<class Elt>
struct Worker{
User& u;
Worker(User& u):u(u){}
template<class Iter>
void set(Iter begin, Iter end);
};
};
struct F{ int x; explicit F(int x):x(x){} };
struct G{ double x; explicit G(double x):x(x){} };
struct User{
Container<F> a;
Container<G> b;
template<class Elt>
void doIt(Elt x, Elt y){
std::vector<Elt> v; v.push_back(x); v.push_back(y);
Worker<Elt>(*this).set(v.begin(), v.end());
}
};
namespace WkNS{
template<class Elt> template<class Iter>
void Worker<Elt>::set(Iter begin, Iter end){
std::cout << "Set a." << std::endl;
u.a.set(begin, end);
}
template<> template<class Iter>
void Worker<G>::set(Iter begin, Iter end){
std::cout << "Set b." << std::endl;
u.b.set(begin, end);
}
};
};
int main(){
using myNS::F; using myNS::G;
myNS::User u;
u.doIt(F(1),F(2));
u.doIt(G(3),G(4));
}
User
是我写的课程。
Worker
是我的帮助班。我在它自己的命名空间中拥有它,因为我不希望它在myNS之外造成麻烦。
Container
是一个容器类,其定义我不想修改,但User
在其实例变量中使用。
doIt<F>
应该修改一个。 doIt<G>
应修改b。
F
和G
可以进行有限修改,如果这样可以产生更优雅的解决方案。 (作为一个这样的修改的一个例子,在实际应用程序中F
的构造函数接受一个伪参数,使其看起来像G
的构造函数,并使我免于重复自己。)
在实际代码中,Worker
是User
的朋友,成员变量是私有的。为了使示例更简单,我将所有内容都公之于众。但是,需要公开的解决方案确实无法回答我的问题。
鉴于所有这些警告,是否有更好的方法来编写User::doIt
?
答案 0 :(得分:1)
在阅读了Emile Cormier的评论之后,我想到了一种方法,既可以不重复自己也可以消除Worker
类:为doIt
制作两个简单的非模板F
函数和G
并且每次调用第三个模板doIt
函数,并将要更改的变量作为参数传递。这是修改后的代码。
#include <vector>
#include <algorithm>
#include <iostream>
namespace myNS{
template<class Elt>
struct Container{
std::vector<Elt> contents;
template<class Iter>
void set(Iter begin, Iter end){
contents.erase(contents.begin(), contents.end());
std::copy(begin, end, back_inserter(contents));
}
};
struct F{ int x; explicit F(int x):x(x){} };
struct G{ double x; explicit G(double x):x(x){} };
struct User{
Container<F> a;
Container<G> b;
template<class Elt>
void doIt(Elt x, Elt y, Container<Elt>& cont, const char*name){
std::vector<Elt> v; v.push_back(x); v.push_back(y);
cont.set(v.begin(), v.end());
std::cout << "Set " << name << std::endl;
}
void doIt(F x, F y){ doIt(x,y,a,"a"); }
void doIt(G x, G y){ doIt(x,y,b,"b"); }
};
}
int main(){
using myNS::F; using myNS::G;
myNS::User u;
u.doIt(F(1),F(2));
u.doIt(G(3),G(4));
}