gpt4 book ai didi

C++如何通过可选的typedef选择类,使用SFINAE或其他

转载 作者:搜寻专家 更新时间:2023-10-31 01:52:55 24 4
gpt4 key购买 nike

用户通过定义指定所需选项的类来自定义库模板类。称之为 list 。这个想法是在 list 中有可选的 typedef。例如,如果用户的 list 包含 H 的 typedef,我希望库代码使用指定的类型作为其“H”。如果用户 list 中没有 typedef,库将使用默认值。

我怀疑有一种优雅的方法可以利用新的 C++11 功能来做到这一点,但我一无所获。我有一个解决方案,基于 SFINAE 的维基百科条目。这是丑陋的。它需要一个新的模板函数 has_typedef_H 用于每个新的 H。我隐约感到不安的是它利用了 0 可以表示整数或空指针的属性。只是看起来太笨拙了。

有没有更好的方法?最好是一个可以在 VC++ 2010 中工作的?

在玩具示例中有五个类,H1、H2 和 U0、U1 和 U2。 H1 和 H2 是库类 L 的“助手”示例。H1 是默认值。 U 是用户定义类的示例。在示例中,我省略了定义库类 L,仅使用 main() 的主体根据 U 中的类型定义(或缺少类型定义)来选择 H。 H2类型的主题。


struct H1{
void operator() (){ std::cout << "H1" << std::endl;}
};

struct H2{
void operator() (){ std::cout << "H2" << std::endl;}
};


struct default_H: public H1 {};

struct U2 {
typedef H2 H;
};

struct U1 {
typedef H1 H;
};

struct U0 {
};


template <typename T>
class has_typedef_H {

typedef char no[false+1];
typedef char yes[true+1];

template
static yes& test(typename C::H*);

template
static no& test(...);

public:
static const bool value = sizeof(test(0))-1;
};


template<typename U, bool >
struct type_H_B: public default_H{};

template<typename U>
struct type_H_B<U, true>: public U::H {};

template<typename U>
struct H_type: public type_H_B<U, has_typedef_H<U>::value> {};

int main() {

H_type<U0> h0;
H_type<U1> h1;
H_type<U2> h2;

// Prints H1 H1 H2
h0();
h1();
h2();
return 0;
}

最佳答案

您真的不需要为每个嵌套类型提供复杂的特征,这可以做得更简单一些。 Here是一个例子:

// Helper to map any type to void, needed by SFINAE below
template <typename T>
struct void_type {
typedef void type;
};

// Selects a nested typedef or a default type D (using a macro to reduce boilerplate):
#define SELECT_NESTED_TYPE( TYPE ) \
template <typename T, typename D, typename _ = void> \
struct select_##TYPE{ \
typedef D type; \
}; \
template <typename T, typename D> \
struct select_##TYPE<T, D, typename void_type<typename T::TYPE>::type> { \
typedef typename T::TYPE type; \
};

SELECT_NESTED_TYPE( int_t );
SELECT_NESTED_TYPE( float_t );
//...
#undef SELECT_NESTED_TYPE

// Use
template <typename T>
class TheTemplate {
public:
typedef typename select_int_t<T,int>::type int_t;
typedef typename select_float_t<T,double>::type float_t;
//....
};

// Test:
template <typename T, typename U> struct same_type {
static const bool value = false;
};
template <typename T> struct same_type<T,T> {
static const bool value = true;
};
struct test1 {
};
struct test2 {
typedef long long int_t;
typedef float float_t;
};
int main() {
// test1 has the default typedefs
assert(( same_type< TheTemplate<test1>::int_t, int>::value ));
assert(( same_type< TheTemplate<test1>::float_t, double>::value ));
// test2 has the ones in the type
assert(( same_type< TheTemplate<test2>::int_t, long long>::value ));
assert(( same_type< TheTemplate<test2>::float_t, float>::value ));
}

如果宏使用默认类型并在默认情况下注入(inject)它(当未定义嵌套类型时),您可以选择提供稍微简单的解决方案。不可否认,这需要为每个嵌套类型创建特征,但特征只是几行代码(并且不太难定义为宏)。或者,如果只有几个潜在的 typedef,您可以在没有额外样板的情况下直接在目标类型上使用 SFINAE。


完全不同的方法......如果可以的话

如果您可以修改库中使用的类型,那么您可以通过滥用继承来使用更简单(虽然不是很 的解决方案)。创建一个仅包含要使用的默认类型的 typedef 的基类,并让每个用户类派生自提供默认类型的类。如果用户想要提供比默认帮助更好的帮助程序,他们只需要提供 typedef。如果他们不提供 typedef,查找将在层次结构的更高层找到默认值:

struct default_helpers {
typedef Helper1 helper1_t;
typedef Helper2 helper2_t;
// ...
};
struct user_type_1 : default_helpers {
};
struct user_type_2 : default_helpers {
typedef MyHelper helper1_t; // I prefer this one...
};
int main() {
assert( same_type< user_type1::helper1_t, default_helpers::helper1_t >::value );
assert( !same_type< user_type2::helper1_t, default_helpers::helper1_t >::value );
assert( same_type< user_type1::helper2_t, user_type2::helper2_t>::value );
}

关于C++如何通过可选的typedef选择类,使用SFINAE或其他,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11875327/

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