![](/img/trans.png)
[英]Get type of a std::variant member at a given index during compile time
[英]Get type from variant at compile time
我需要對變量類型在編譯時是否可以容納類型進行類型檢查。
我正在將枚舉和字符串轉換為變量,但我希望該庫與用戶提供的變量兼容(針對它們支持的類型)。 因此,我有一個模板參數CustomVariant
來表示受支持類型的子集AlphaBeta
, Gamma
, Delta
和Epsilon
。 如果我無法創建有效的變體,我想返回std::nullopt
。
template <typename CustomVariant>
std::optional<CustomVariant> AsCustomVariant(LargeEnum type, const std::string& name) {
case LargeEnum::ALPHA:
case LargeEnum::BETA:
return ConvertAlphaBeta(name);
case LargeEnum::GAMMA:
return ConvertGamma(name);
case LargeEnum::DELTA:
return ConvertDelta(name);
case LargeEnum::EPSILON:
return ConvertEpsilon(name);
default:
return std::nullopt;
}
這個想法是使用某種模板魔術可以執行以下操作:
if (std::type_can_convert<CustomVariant, Gamma>) {
return ConvertGamma(name);
} else {
return std::nullopt;
}
使用c ++ 17(我知道它帶有c ++ 11標記),這非常容易-您甚至不必真正做任何事情:
#include <variant>
#include <type_traits>
#include <string>
using namespace std;
int main() {
// this works, as expected
if constexpr(is_constructible_v<variant<int>, double>) {
// this will run
}
// this is fine - it just won't happen,
if constexpr(is_constructible_v<variant<int>, string>) {
// this won't run
} else {
// this will run
}
// but obviously the assignment of a string into that variant doesn't work...
variant<int> vi="asdf"s;
}
首先,我會這樣做:
template<class T>struct tag_t{using type=T;};
template<class T>constexpr tag_t<T> tag{};
template<class...Ts>using one_tag_of=std::variant<tag_t<Ts>...>;
using which_type=one_tag_of<AlphaBeta, Gamma, Delta /* etc */>;
which_type GetType(LargeEnum e){
switch (e){
case LargeEnum::Alpha:
case LargeEnum::Beta: return tag<AlphaBeta>;
// etc
}
}
現在我們這樣做:
template <typename CustomVariant>
std::optional<CustomVariant> AsCustomVariant(LargeEnum type, const std::string& name) {
auto which = GetType(type);
return std::visit( [&name](auto tag)->std::optional<CustomVariant>{
using type=typename decltype(tag)::type;
if constexpr (std::is_convertible<CustomVariant, type>{})
return MakeFromString( tag, name );
return std::nullopt;
}, which );
}
這留下了MakeFromString
。
編寫這樣的重載:
inline Delta MakeFromString(tag_t<Delta>, std::string const& name){ return ConvertDelta(name); }
注意,不是專業。 只是超載。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.