私のプロジェクトの一つでは、私はboost-variant
を過度に使っています。ある時点で、私はboost-variant
のテンプレートパラメータの最大数(20)を超えました。そこで、いくつかのタイプをリンクされたリストのようにリンクして、以下の解決法を導き出しました。コード複製を削除するためにboost :: static-visitorから派生しました
#include <boost/variant.hpp>
#include <iostream>
template<int T> struct A {
const int value = T;
};
typedef boost::variant<
A<20>,A<21>,A<22>,A<23>,A<24>,A<25>,A<26>,A<27>,A<28>,A<29>,A<30>,A<31>,A<32>,A<33>,A<34>,A<35>,A<36>,A<37>,A<38>,A<39>
> NextVar;
typedef boost::variant<
A<1>,A<2>,A<3>,A<4>,A<5>,A<6>,A<7>,A<8>,A<9>,A<10>,A<11>,A<12>,A<13>,A<14>,A<15>,A<16>,A<17>,A<18>,A<19>,NextVar
> TVar;
struct PrintVisitor : public boost::static_visitor<std::string> {
result_type operator()(const NextVar& n) {
return n.apply_visitor(*this);
}
template<int T>
result_type operator()(const A<T>& a) {
return std::to_string(a.value);
}
};
struct IntVisitor : public boost::static_visitor<int> {
result_type operator()(const NextVar& n) {
return n.apply_visitor(*this);
}
template<int T>
result_type operator()(const A<T>& a) {
return a.value;
}
};
template<int I>
struct AddVisitor : public boost::static_visitor<int> {
result_type operator()(const NextVar& n) {
return n.apply_visitor(*this);
}
template<int T>
result_type operator()(const A<T>& a) {
return a.value+I;
}
};
int main(int argc, char **args) {
TVar x = A<35>();
PrintVisitor v1;
std::cout << x.apply_visitor(v1) << std::endl;
IntVisitor v2;
std::cout << x.apply_visitor(v2) << std::endl;
AddVisitor<10> v3;
std::cout << x.apply_visitor(v3) << std::endl;
}
この回避策が私の問題をどれほどうまく解決したかは本当に驚きました。まだ塩の穀物があった。訪問者ごとに、次の行を含める必要がありました。
result_type operator()(const NextVar& n) {
return n.apply_visitor(*this);
}
これは、不要なコードの重複のようです。もっと悪いことに、もし私がboost-variant
で60以上のタイプを必要とするならば。私は、以下に示すようにBaseVisitor
から派生する問題を解決するだろうと、思っ
template<typename T>
struct BaseVisitor : public boost::static_visitor<T> {
result_type operator()(const NextVar& n) {
return n.apply_visitor(*this);
}
};
:私の試みは私の訪問者のすべてに共通の基本クラスを定義することでした
struct PrintVisitor : public BaseVisitor<std::string> {
template<int T>
result_type operator()(const A<T>& a) {
return std::to_string(a.value);
}
};
しかし、その代わりに、コンパイラは文句:
template-argument for "const A<T> &" could not be derived from "T19"
この種の問題に最も近い回避策はありますか?
速い返信と素晴らしいソリューションをありがとう。残念ながら、いくつかの制限があり、 'BOOST_MP_LIMIT_LIST_SIZE'を使用することはできません。あなたのソリューションは間違いなく機能しています。 CRTPはそれほど明らかではありません。 :-) 派生クラスでクラッタ(テンプレートエイリアスコード)を削除することは可能でしょうか? – Aleph0
@FrankSimonデモの31行目と44行目を除く(テンプレートクラスではありません)、いいえ。しかし、私たちのコードを少し修正することによって...版を参照してください。 –
本当に素晴らしい。あなたのソリューションを消化するまでには時間がかかります。どうもありがとう。私はプロダクションコードでそれを使用します。 – Aleph0