- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
用户通过定义指定所需选项的类来自定义库模板类。称之为 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/
C++11 专家的几个问题。 我正在与 SFINAE 打交道,我遇到了一个奇怪的情况,其中 g++ (4.9.2) 和 clang++ (3.5.0) 的行为不同。 我准备了以下示例代码。很抱歉,我无
这些天我正在试验 SFINAE,有些事情让我很困惑。为什么 my_type_a不能在 my_function 中推导出来的实例化? class my_type_a {}; template clas
我正在尝试复制(我猜)典型的 SFINAE 示例来判断一个类型是否具有特定方法。我的代码基本上是 the one found in the accepted answer of a previous
出于学术原因,我想实现一个示例,如果非类型模板参数满足给定条件,则选择一个模板。例如,我想要一个只为奇数定义的函数。 可以这样做: template struct is_odd: public st
有没有办法检查两个可变参数包的串联是否与第三个可变参数包相同。 template struct ClassOne { } template struct ClassTwo { } template s
为什么以下代码无法编译?为具有特定成员的类型启用模板的最简洁的解决方案是什么?如果模板变量被直接用于初始化它的表达式替换,它也会编译。 #include template constexpr boo
代码: #include using std::nullptr_t; template using nullptr_vt = nullptr_t; struct not_addable{}; tem
我有一个模板类,我想有两个复制 ctor。一个用于平凡类型,另一个用于非平凡类型。 以下代码有效(使用一个拷贝 ctor): template struct MyStruct { MySt
我一直在尝试定义一个辅助类来帮助我使用模板方法,在该方法中我希望为复杂类型和实际类型提供通用实现。 到目前为止,这是我的尝试: #include #include template struct is
这个问题已经有答案了: Officially, what is typename for? [duplicate] (8 个回答) 已关闭 3 年前。 我正在研究现代 C++ 中的 SFINAE,我看
我有一个 std::variants 包含具有不同接口(interface)的对象。目标是如果变体中的对象具有某些方法,则调用它。 我正在尝试制作几个模板装饰器,并寻找一种方法来使用更少的样板和没有宏
我有一个代码,它接受一个函数并根据函数签名执行它,如下所示: template struct Value { int value[Num]; }; struct Executor { t
我一直在尝试定义一个辅助类来帮助我使用模板方法,在该方法中我希望为复杂类型和实际类型提供通用实现。 到目前为止,这是我的尝试: #include #include template struct is
在此视频中https://youtu.be/Vkck4EU2lOU?t=582 “标签调度”和SFINAE作为替代方案出现,允许实现所需模板功能的选择。 正确吗? “标签发送”不是使用SFINAE吗?
我认为下面的代码会编译,因为冲突的重载是 SFINAEd 了。但是编译器(GCC)说:void Foo::bar(Xd) const' cannot be overloaded .有没有简单的方法来修
#define BINDINGTEMPLATE template, int> || std::is_same_v, std::string> || std::is_same_v, char>>> 这样
SFINAE 是否在概念论证中起作用? (也许这里不叫 SFINAE)。例子: template requires std::invocable && // , void>)
在他的演讲现代模板元编程:纲要第 I 部分中,Walter Brown 以他的方式讨论了 enable_if 与 SFINAE 的交互。 在大约 47:40 的谈话中,他被问到一个问题,我无法完全匹配
我正在尝试对同一函数进行两次重载,称为某物。这个函数应该以另一个函数作为参数,并且它应该根据这个另一个函数的返回类型进行重载。到目前为止我有这个: #include #include using
以下代码特化了 f() 的两个版本。第一个检测一个 vector 并返回一个迭代器。第二个接受所有其他类型并返回一个拷贝。 这无法在 VC 2010 上编译,GetIter2 中有一个错误,即 Get
我是一名优秀的程序员,十分优秀!