gpt4 book ai didi

C++ 和类型特征 : simplest way of defining a list of possible definitions

转载 作者:行者123 更新时间:2023-11-30 02:05:26 25 4
gpt4 key购买 nike

我想定义一个函数template<typename T> T constCast(const ScriptVar_t& s); .取决于T ,我想有不同的定义。 (ScriptVar_t 是一个类,但细节在这里并不重要。)

关于 T 的条件不像特定类型那么简单,它们都是稍微复杂一些的静态 bool 表达式。 IE。我有一个表达式列表 ext1 .. extN对于每个函数,我都有该函数的定义。我希望按顺序检查它们,并且应该使用第一个匹配表达式的定义。如果它们都失败了,我想得到一个编译器错误。

现在,我只有 2 个定义,我的代码如下所示(这是一个完整的测试用例,已标记相关代码):

#include <boost/type_traits.hpp>

enum {
SVT_INT,
SVT_FLOAT,
SVT_BASEOBJ,
SVT_CUSTOMVAR
};

struct BaseObject {};
struct CustomVar {};

template<typename T> struct GetType;
template<> struct GetType<int> { static const int value = SVT_INT; };
template<> struct GetType<float> { static const int value = SVT_FLOAT; };
template<> struct GetType<BaseObject> { static const int value = SVT_BASEOBJ; };

template<bool> struct GetType_BaseCustomVar;
template<> struct GetType_BaseCustomVar<true> {
struct Type { static const int value = SVT_CUSTOMVAR; };
};
template<typename T> struct GetType : GetType_BaseCustomVar<boost::is_base_of<CustomVar,T>::value>::Type {};

struct ScriptVar_t;
template<typename T> T CastScriptVarConst(const ScriptVar_t& s);

struct ScriptVar_t {
operator int() const { return 0; }
operator float() const { return 0.0f; }
operator BaseObject() const { return BaseObject(); }
template<typename T> T* as() const { return NULL; }

template <typename T> T castConst() const { return CastScriptVarConst<T>(*this); }
};

// *** relevant code starts here

template<typename T> T CastScriptVarConst(const ScriptVar_t& s);

template<bool> struct CastScriptVar1;
template<typename T> struct CastScriptVar1_IsSimpleType {
static const bool value = GetType<T>::value < SVT_BASEOBJ;
};
template<> struct CastScriptVar1<true> {
template<typename T> static T castConst(const ScriptVar_t& s, const T& /*dummy*/) { return (T) s; }
};

template<bool> struct CastScriptVar2;
template<typename T> struct CastScriptVar2_IsCustomVar {
static const bool value = boost::is_base_of<CustomVar,T>::value;
};
template<> struct CastScriptVar2<true> {
template<typename T> static T castConst(const ScriptVar_t& s, const T& /*dummy*/) { return *s.as<T>(); }
};

template<> struct CastScriptVar1<false> {
template<typename T> static T castConst(const ScriptVar_t& s, const T& /*dummy*/) {
return CastScriptVar2<CastScriptVar2_IsCustomVar<T>::value>::castConst(s, T());
}
};
template<typename T> T CastScriptVarConst(const ScriptVar_t& s) {
return CastScriptVar1<CastScriptVar1_IsSimpleType<T>::value>::castConst(s, T());
}

int main() {
ScriptVar_t v;
v.castConst<int>();
v.castConst<CustomVar>();
}

经过几次尝试,我想出了这个办法,直到它成功为止。

(从代码中可以看出,这两个表达式是GetType<T>::value < SVT_BASEOBJboost::is_base_of<CustomVar,T>::value,如果都为false,编译器应该会报错。但这只是我的问题的一个例子。)

我想知道这段代码是否有更简洁的解决方案。


作为引用,我正在玩它here .现在,我又有了一个与此处所有其他解决方案略有不同的解决方案。

最佳答案

所以如果我没理解错的话,你有两种施法方法。如果GetType<T>::value < SVT_BASEOBJ那么你只想使用普通类型转换:(T) s;

另一方面,如果GetType<T>::value < SVT_BASEOBJ是 false 那么你要确保 CustomVarT 类型的基类(即 T 派生自 CustomVar )。然后你想在那个对象上使用一个成员函数:*s.as<T>()

否则会出现编译错误。

这是使用重载和 std::enable_if 实现的一种方法:

template<typename T>
typename std::enable_if<GetType<T>::value < SVT_BASEOBJ,T>::type
CastScriptVarConst(const ScriptVar_t& s) {
return (T) s;
}

template<typename T>
typename std::enable_if<!(GetType<T>::value < SVT_BASEOBJ)
&& std::is_base_of<CustomVar,T>::value,T>::type
CastScriptVarConst(const ScriptVar_t& s) {
return *s.as<T>();
}

enable_if利用 C++ 中的 SFINAE 规则,因此如果条件失败,唯一的后果是该函数不会添加到该调用的可行重载集中。自 enable_if条件是相互排斥的,至多一个函数对于任何给定的调用都是可行的,因此永远不会有歧义。如果这两个条件都不成立,那么您将收到一个编译错误,提示找不到匹配的函数。


#include <type_traits>
#include <iostream>

enum {
SVT_INT,
SVT_FLOAT,
SVT_BASEOBJ,
SVT_CUSTOMVAR
};

struct BaseObject {};
struct CustomVar {};

template<typename T> struct GetType;
template<> struct GetType<int> { static const int value = SVT_INT; };
template<> struct GetType<float> { static const int value = SVT_FLOAT; };
template<> struct GetType<BaseObject> { static const int value = SVT_BASEOBJ; };

template<bool> struct GetType_BaseCustomVar;
template<> struct GetType_BaseCustomVar<true> {
struct Type { static const int value = SVT_CUSTOMVAR; };
};
template<typename T> struct GetType : GetType_BaseCustomVar<std::is_base_of<CustomVar,T>::value>::Type {};

struct ScriptVar_t {
operator int() const { return 0; }
operator float() const { return 0.0f; }
operator BaseObject() const { return BaseObject(); }
template<typename T> T* as() const { return NULL; }

template <typename T> T castConst() const;
};

template<typename T>
typename std::enable_if<GetType<T>::value < SVT_BASEOBJ,T>::type
CastScriptVarConst(const ScriptVar_t& s) {
std::cout << "value < SVT_BASEOBJT\n";
return (T) s;
}

template<typename T>
typename std::enable_if<!(GetType<T>::value < SVT_BASEOBJ)
&& std::is_base_of<CustomVar,T>::value,T>::type
CastScriptVarConst(const ScriptVar_t& s) {
std::cout << "CustomVar\n";
return *s.as<T>();
}

template <typename T>
T ScriptVar_t::castConst() const {
return CastScriptVarConst<T>(*this);
}

int main() {
ScriptVar_t v;
v.castConst<int>();
v.castConst<CustomVar>();
}

关于C++ 和类型特征 : simplest way of defining a list of possible definitions,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9570985/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com