所以我一直在和这个争斗一段时间,这也是我在这里发表的第一篇文章。我只想知道,如果我传入一个肯定是前向容器的容器,如boost中定义的那样,我怎么能以进一步检查代码是否为BackInsertionSequence或FrontInsertionSequence的方式编写代码并执行,具体取决于哪个这是什么类型的?
template <class SequentialContainer>
void MyClass<SequentialContainer>::SaySomething() {
BOOST_CONCEPT_ASSERT((boost::ForwardContainer<SequentialContainer>));
if (boost::BackInsertionSequence<SequentialContainer> == true) {
//do something
} else {
//say something else
}
}
答案 0 :(得分:2)
如果你像那里那样进行了if
检查,那么无论是否只为特定类型执行一个分支,都必须编译这两个分支。这严重限制了简单if
的有用性 - 你需要一个构造,只有一个分支甚至可以编译。
有两种常见的方法可以做到这一点。标签发送:
template <class SequentialContainer>
void MyClass<SequentialContainer>::SaySomething() {
SaySomething<SequentialContainer>(
is_back_insertion_sequence<SequentialContainer>{}
);
}
template <class SequentialContainer>
void SaySomething(std::true_type /* back insertion sequence */ ) { ... }
template <class SequentialContainer>
void SaySomething(std::false_type /* NOT back insertion sequence */ ) { ... }
和SFINAE:
template <class SequentialContainer>
typename std::enable_if<
is_back_insertion_sequence<SequentialContainer>::value
>::type
SaySomething() {
/* back insertion sequence */
}
template <class SequentialContainer>
typename std::enable_if<
!is_back_insertion_sequence<SequentialContainer>::value
>::type
SaySomething() {
/* NOT back insertion sequence */
}
两者都有优点和缺点,但如果它只是你要检查的一面旗帜 - 它主要是一个意见问题。
答案 1 :(得分:1)
这是一个C ++ 14尝试纯粹在函数内执行编译时分支。我不知道这是不是一个好主意。
template<
template<class...>class Test, class Arg,
class F1, class F2,
class=std::enable_if_t<
Test<Arg>{}
>
>
std::result_of_t< F1(Arg) > branch( Arg&& arg, F1&& f1, F2&& f2 ) {
return std::forward<F1>(f1)(std::forward<Arg>(arg));
};
template<
template<class...>class Test, class Arg,
class F1, class F2,
class=std::enable_if_t<
!Test<Arg>{}
>
>
std::result_of_t< F2(Arg) > branch( Arg&& arg, F1&& f1, F2&& f2 ) {
return std::forward<F2>(f2)(std::forward<Arg>(arg));
};
这是一个编译时分支机构。然后我们这样做:
template <class SequentialContainer>
void SaySomething() {
branch<boost::BackInsertionSequence>( container,
[&](auto&& container){ // true
}, [&](auto&& container){ // false
});
}
此处我们测试container
以确定它是否为boost::BackInsertionSequence
。如果是这样,我们运行第一个分支,如果不是第二个分支。
根据标准,每个分支中的代码必须具有有效的特化:这就是我传递容器的原因。我们可以假设测试容器在代码中具有我们想要的属性。