![](/img/trans.png)
[英]How can I implement derived-class constructors by reusing base-class constructors?
[英]How to implement a boost::variant derived-class?
我已經嘗試了幾個小時來編寫一個派生自boost::variant
。 但我不明白是什么問題(我不明白編譯錯誤意味着什么)。
實現一個干凈的boost::variant
派生類有哪些規則?
#include <boost/variant.hpp>
class MyVariant : public boost::variant<char,bool>
{
public:
MyVariant () : boost::variant<char,bool>( ) {}
template <typename T>
MyVariant( T& v) : boost::variant<char,bool>(v) {}
template <typename T>
MyVariant(const T& v) : boost::variant<char,bool>(v) {}
};
int main ()
{
MyVariant a;
MyVariant b = a; //compilation error
// MyVariant c = MyVariant();
// MyVariant d (true);
// MyVariant e ('E');
}
為什么我要使用繼承? (編輯給@zaufi更多細節)
const char*
作為string
int
long
enum
類型 例如,在偽C ++代碼中,我希望:
class MyVariant : public boost::variant<char,bool,long,std::string>
{
typedef boost::variant<char,bool,long,std::string> super;
public:
// I know here I should specialize templeted constructors
// but I is more clear like that, isn't it?
MyVariant() : super('e') {} //empty -> char
MyVariant(char c) : super(std::string(1,c)){} //char -> string
MyVariant(const char* s) : super(std::string(s) ) {} //char* -> string
MyVariant(int v) : super(long (v) ) {} //TODO boundaries
/* other constructors ... */
enum Type
{
NONE, //my empty state = char type
BOOL,
LONG,
STRING
};
Type type() const { return (Type) which(); }
};
基本代碼段(在問題的頂部)已在不同平台上進行了測試
下面我的兩個版本的GCC的錯誤(如果它困擾某人,我可以刪除其中一個......)
$ g++ --version
g++ (GCC) 4.1.2 20080704 (Red Hat 4.1.2-52)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ g++ myVariant.cpp
/usr/include/boost/variant/variant.hpp: In constructor 'boost::variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>::variant(T&) [with T = MyVariant, T0_ = char, T1 = bool, T2 = boost::detail::variant::void_, T3 = boost::detail::variant::void_, T4 = boost::detail::variant::void_, T5 = boost::detail::variant::void_, T6 = boost::detail::variant::void_, T7 = boost::detail::variant::void_, T8 = boost::detail::variant::void_, T9 = boost::detail::variant::void_, T10 = boost::detail::variant::void_, T11 = boost::detail::variant::void_, T12 = boost::detail::variant::void_, T13 = boost::detail::variant::void_, T14 = boost::detail::variant::void_, T15 = boost::detail::variant::void_, T16 = boost::detail::variant::void_, T17 = boost::detail::variant::void_, T18 = boost::detail::variant::void_, T19 = boost::detail::variant::void_]':
myVariant.cpp:10: instantiated from 'MyVariant::MyVariant(T&) [with T = MyVariant]'
myVariant.cpp:19: instantiated from here
/usr/include/boost/variant/variant.hpp:1348: error: call of overloaded 'convert_construct(MyVariant&, long int)' is ambiguous
/usr/include/boost/variant/variant.hpp:1262: note: candidates are: void boost::variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>::convert_construct(T&, int, mpl_::false_) [with T = MyVariant, T0_ = char, T1 = bool, T2 = boost::detail::variant::void_, T3 = boost::detail::variant::void_, T4 = boost::detail::variant::void_, T5 = boost::detail::variant::void_, T6 = boost::detail::variant::void_, T7 = boost::detail::variant::void_, T8 = boost::detail::variant::void_, T9 = boost::detail::variant::void_, T10 = boost::detail::variant::void_, T11 = boost::detail::variant::void_, T12 = boost::detail::variant::void_, T13 = boost::detail::variant::void_, T14 = boost::detail::variant::void_, T15 = boost::detail::variant::void_, T16 = boost::detail::variant::void_, T17 = boost::detail::variant::void_, T18 = boost::detail::variant::void_, T19 = boost::detail::variant::void_]
/usr/include/boost/variant/variant.hpp:1321: note: void boost::variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>::convert_construct(boost::variant<U0, U1, U2, U3, U4, U5, U6, U7, U8, U9, U10, U11, U12, U13, U14, U15, U16, U17, U18, U19>&, long int) [with U0 = char, U1 = bool, U2 = boost::detail::variant::void_, U3 = boost::detail::variant::void_, U4 = boost::detail::variant::void_, U5 = boost::detail::variant::void_, U6 = boost::detail::variant::void_, U7 = boost::detail::variant::void_, U8 = boost::detail::variant::void_, U9 = boost::detail::variant::void_, U10 = boost::detail::variant::void_, U11 = boost::detail::variant::void_, U12 = boost::detail::variant::void_, U13 = boost::detail::variant::void_, U14 = boost::detail::variant::void_, U15 = boost::detail::variant::void_, U16 = boost::detail::variant::void_, U17 = boost::detail::variant::void_, U18 = boost::detail::variant::void_, U19 = boost::detail::variant::void_, T0_ = char, T1 = bool, T2 = boost::detail::variant::void_, T3 = boost::detail::variant::void_, T4 = boost::detail::variant::void_, T5 = boost::detail::variant::void_, T6 = boost::detail::variant::void_, T7 = boost::detail::variant::void_, T8 = boost::detail::variant::void_, T9 = boost::detail::variant::void_, T10 = boost::detail::variant::void_, T11 = boost::detail::variant::void_, T12 = boost::detail::variant::void_, T13 = boost::detail::variant::void_, T14 = boost::detail::variant::void_, T15 = boost::detail::variant::void_, T16 = boost::detail::variant::void_, T17 = boost::detail::variant::void_, T18 = boost::detail::variant::void_, T19 = boost::detail::variant::void_]
/usr/include/boost/variant/variant.hpp:1330: note: void boost::variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>::convert_construct(const boost::variant<U0, U1, U2, U3, U4, U5, U6, U7, U8, U9, U10, U11, U12, U13, U14, U15, U16, U17, U18, U19>&, long int) [with U0 = char, U1 = bool, U2 = boost::detail::variant::void_, U3 = boost::detail::variant::void_, U4 = boost::detail::variant::void_, U5 = boost::detail::variant::void_, U6 = boost::detail::variant::void_, U7 = boost::detail::variant::void_, U8 = boost::detail::variant::void_, U9 = boost::detail::variant::void_, U10 = boost::detail::variant::void_, U11 = boost::detail::variant::void_, U12 = boost::detail::variant::void_, U13 = boost::detail::variant::void_, U14 = boost::detail::variant::void_, U15 = boost::detail::variant::void_, U16 = boost::detail::variant::void_, U17 = boost::detail::variant::void_, U18 = boost::detail::variant::void_, U19 = boost::detail::variant::void_, T0_ = char, T1 = bool, T2 = boost::detail::variant::void_, T3 = boost::detail::variant::void_, T4 = boost::detail::variant::void_, T5 = boost::detail::variant::void_, T6 = boost::detail::variant::void_, T7 = boost::detail::variant::void_, T8 = boost::detail::variant::void_, T9 = boost::detail::variant::void_, T10 = boost::detail::variant::void_, T11 = boost::detail::variant::void_, T12 = boost::detail::variant::void_, T13 = boost::detail::variant::void_, T14 = boost::detail::variant::void_, T15 = boost::detail::variant::void_, T16 = boost::detail::variant::void_, T17 = boost::detail::variant::void_, T18 = boost::detail::variant::void_, T19 = boost::detail::variant::void_]
$ g++ --version
g++.exe (GCC) 4.7.2
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ g++ myVariant.cpp -I /c/.../include/
In file included from c:/.../include/boost/variant.hpp:17:0,
from myVariant.cpp:1:
c:/.../include/boost/variant/variant.hpp: In instantiation of 'boost::variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>::variant(T&) [with T = MyVariant; T0_ = char; T1 = bool; T2 = boost::detail::variant::void_; T3 = boost::detail::variant::void_; T4 = boost::detail::variant::void_; T5 = boost::detail::variant::void_; T6 = boost::detail::variant::void_; T7 = boost::detail::variant::void_; T8 = boost::detail::variant::void_; T9 = boost::detail::variant::void_; T10 = boost::detail::variant::void_; T11 = boost::detail::variant::void_; T12 = boost::detail::variant::void_; T13 = boost::detail::variant::void_; T14 = boost::detail::variant::void_; T15 = boost::detail::variant::void_; T16 = boost::detail::variant::void_; T17 = boost::detail::variant::void_; T18 = boost::detail::variant::void_; T19 = boost::detail::variant::void_]':
myVariant.cpp:9:66: required from 'MyVariant::MyVariant(T&) [with T = MyVariant]'
myVariant.cpp:18:25: required from here
c:/.../include/boost/variant/variant.hpp:1406:9: error: call of overloaded convert_construct(MyVariant&, long int)' is ambiguous
c:/.../include/boost/variant/variant.hpp:1406:9: note: candidates are:
c:/.../include/boost/variant/variant.hpp:1316:10: note: void boost::variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>::convert_construct(T&, int, mpl_::false_) [with T = MyVariant; T0_ = char; T1 = bool; T2 = boost::detail::variant::void_; T3 = boost::detail::variant::void_; T4 = boost::detail::variant::void_; T5 = boost::detail::variant::void_; T6 = boost::detail::variant::void_; T7 = boost::detail::variant::void_; T8 = boost::detail::variant::void_; T9 = boost::detail::variant::void_; T10 = boost::detail::variant::void_; T11 = boost::detail::variant::void_; T12 = boost::detail::variant::void_; T13 = boost::detail::variant::void_; T14 = boost::detail::variant::void_; T15 = boost::detail::variant::void_; T16 = boost::detail::variant::void_; T17 = boost::detail::variant::void_; T18 = boost::detail::variant::void_; T19 = boost::detail::variant::void_; mpl_::false_ = mpl_::bool_<false>]
c:/.../include/boost/variant/variant.hpp:1376:10: note: void boost::variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>::convert_construct(boost::variant<U0, U1, U2, U3, U4, U5, U6, U7, U8, U9, U10, U11, U12, U13, U14, U15, U16, U17, U18, U19>&, long int) [with U0 = char; U1 = bool; U2 = boost::detail::variant::void_; U3 = boost::detail::variant::void_; U4 = boost::detail::variant::void_; U5 = boost::detail::variant::void_; U6 = boost::detail::variant::void_; U7 = boost::detail::variant::void_; U8 = boost::detail::variant::void_; U9 = boost::detail::variant::void_; U10 = boost::detail::variant::void_; U11 = boost::detail::variant::void_; U12 = boost::detail::variant::void_; U13 = boost::detail::variant::void_; U14 = boost::detail::variant::void_; U15 = boost::detail::variant::void_; U16 = boost::detail::variant::void_; U17 = boost::detail::variant::void_; U18 = boost::detail::variant::void_; U19 = boost::detail::variant::void_; T0_ = char; T1 = bool; T2 = boost::detail::variant::void_; T3 = boost::detail::variant::void_; T4 = boost::detail::variant::void_; T5 = boost::detail::variant::void_; T6 = boost::detail::variant::void_; T7 = boost::detail::variant::void_; T8 = boost::detail::variant::void_; T9 = boost::detail::variant::void_; T10 = boost::detail::variant::void_; T11 = boost::detail::variant::void_; T12 = boost::detail::variant::void_; T13 = boost::detail::variant::void_; T14 = boost::detail::variant::void_; T15 = boost::detail::variant::void_; T16 = boost::detail::variant::void_; T17 = boost::detail::variant::void_; T18 = boost::detail::variant::void_; T19 = boost::detail::variant::void_]
c:/.../include/boost/variant/variant.hpp:1385:10: note: void boost::variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>::convert_construct(const boost::variant<U0, U1, U2, U3, U4, U5, U6, U7, U8, U9, U10, U11, U12, U13, U14, U15, U16, U17, U18, U19>&, long int) [with U0 = char; U1 = bool; U2 = boost::detail::variant::void_; U3 = boost::detail::variant::void_; U4 = boost::detail::variant::void_; U5 = boost::detail::variant::void_; U6 = boost::detail::variant::void_; U7 = boost::detail::variant::void_; U8 = boost::detail::variant::void_; U9 = boost::detail::variant::void_; U10 = boost::detail::variant::void_; U11 = boost::detail::variant::void_; U12 = boost::detail::variant::void_; U13 = boost::detail::variant::void_; U14 = boost::detail::variant::void_; U15 = boost::detail::variant::void_; U16 = boost::detail::variant::void_; U17 = boost::detail::variant::void_; U18 = boost::detail::variant::void_; U19 = boost::detail::variant::void_; T0_ = char; T1 = bool; T2 = boost::detail::variant::void_; T3 = boost::detail::variant::void_; T4 = boost::detail::variant::void_; T5 = boost::detail::variant::void_; T6 = boost::detail::variant::void_; T7 = boost::detail::variant::void_; T8 = boost::detail::variant::void_; T9 = boost::detail::variant::void_; T10 = boost::detail::variant::void_; T11 = boost::detail::variant::void_; T12 = boost::detail::variant::void_; T13 = boost::detail::variant::void_; T14 = boost::detail::variant::void_; T15 = boost::detail::variant::void_; T16 = boost::detail::variant::void_; T17 = boost::detail::variant::void_; T18 = boost::detail::variant::void_; T19 = boost::detail::variant::void_]
接受的答案和其他答案都沒有回答這個問題。 有很好的理由從boost :: variant派生出來。
boost::apply_visitor(visitor(), variant)
而不必跳過籃球 下面是一個繼承自boost::variant
MyVariant
類型的工作示例。 該代碼要求C ++ 11繼承boost::variant
的(復雜)構造函數。
編輯:在boost::variant
實現的相等比較等運算符不會自動適用於派生類。 這是boost::variant
實現方式的(非預期)結果,它明確阻止了使用模板與“外來”類型的比較。 可以使用顯式重載啟用運算符,如示例中所示。
#include<iostream>
#include<boost/variant.hpp>
struct type_size_visitor : public boost::static_visitor<unsigned> {
template <typename T>
unsigned operator()(const T&) const { return sizeof(T); }
};
template <typename... Types>
class MyVariant : public boost::variant<Types...>
{
using base_type = boost::variant<Types...>;
public:
// inherit constructors
using base_type::base_type;
// add a new method
unsigned type_size() { return boost::apply_visitor(type_size_visitor(), *this); }
/* Inheriting operators from boost::variant does not
work as it normally would. We have to add explicit
overloads for the operators we want to use.
*/
bool operator==(const MyVariant& rhs) const {
// cast rhs to base and delegate to operator in base
return base_type::operator==(static_cast<const base_type&>(rhs));
}
};
int main() {
MyVariant<std::string, char> v;
v = 1;
std::cout << v.type_size() << " " << sizeof(char) << std::endl;
v = std::string("foo");
std::cout << v.type_size() << " " << sizeof(std::string) << std::endl;
// comparison operators need workaround shown above
MyVariant<std::string, char> a, b;
a = 1; b = 1;
assert(a == b);
}
我想要一個空狀態
boost::variant<boost::blank, bool, long, std::string>
那里。 那更容易。 不需要雜亂的繼承。
我想給枚舉類型
enum Type
{
NONE,
BOOL,
LONG,
STRING
};
struct GetType : public boost::static_visitor<Type>
{
Type operator()(boost::blank) {return NONE;}
Type operator()(bool) {return BOOL;}
Type operator()(long) {return LONG;}
Type operator()(const std::string&) {return STRING;}
};
//Get the type
Type t = boost::apply_visitor(GetType(), theData);
這也很容易。 另外,如果向變體添加新類型,如果不更新GetType
以匹配,則代碼將中斷。
另外兩個條件要求您使用類,但不需要繼承。 你需要收容。
typedef boost::variant<boost::blank, std::string, long> VarType;
class MyVariant
{
public:
//Default construction will initialize with boost::blank.
MyVariant(char c) : m_var(std::string(1,c)) {}
MyVariant(const char* s) : m_var(std::string(s)) {}
MyVariant(int v) : m_var(long(v)) {}
MyVariant(long v) : m_var(long(v)) {}
VarType &operator *() {return m_var;}
const VarType &operator *() const {return m_var;}
private:
VarType m_var;
};
...
Type t = boost::apply_visitor(GetType(), *theData);
最后我的實施基於Nicol Bolas的回答:
Variant.h
class Variant
{
public:
Variant() : v_(boost::blank()) {}
Variant(bool v) : v_(v) {}
Variant(long v) : v_(v) {}
Variant(int v) : v_(long(v)) {}
Variant(double v) : v_(v) {}
Variant(const std::string& s) : v_(s) {}
Variant(const char* s) : v_(std::string(s)) {}
typedef boost::variant <boost::blank, bool,
long, double, std::string> bstvar;
enum Type {
NONE, BOOL, // above underlying types
LONG, DOUBLE, STRING // and enum must be consistent:
}; // (order must be same)
operator bstvar& () { return v_; }
operator const bstvar& () const { return v_; }
bstvar & operator*() { return v_; }
bstvar const& operator*() const { return v_; }
bool empty () const { return type() == NONE; }
bool toBool () const { return boost::get<bool > (v_); }
long toLong () const { return boost::get<long > (v_); }
double toDouble () const { return boost::get<double> (v_); }
std::string const& toStr () const { return boost::get<std::string> (v_); }
std::string & toStr () { return boost::get<std::string> (v_); }
inline Type type () const { return (Type) v_.which(); }
static Type type (const std::string&);
static std::string type (Type t);
private: bstvar v_; // Data
};
Variant.cpp
#include "Variant.h"
#include <sstream>
#include <algorithm> //std::transform
Variant::Type Variant::type (const std::string& str)
{
std::string lower = str;
std::transform (lower.begin(), lower.end(), lower.begin(), ::tolower);
if (lower == "bool") return BOOL;
if (lower == "long") return LONG;
if (lower == "double") return DOUBLE;
if (lower == "string") return STRING;
else return NONE;
}
std::string Variant::type (Type t)
{
switch (t)
{
case NONE: return "none";
case BOOL: return "bool";
case LONG: return "long";
case DOUBLE: return "double";
case STRING: return "string";
default:
;//see below
}
std::ostringstream oss;
oss <<"Unexpected type="<< t;
return oss.str();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.