我看到了这段代码,这让我很困惑:
#include <boost/static_assert.hpp>
#include <boost/type_traits.hpp>
#include <boost/utility/enable_if.hpp>
template<class TT, typename Enable = void> struct UU { BOOST_STATIC_ASSERT_MSG(sizeof(TT) == 0, "undefined UU"); };
template<class TT>
struct UU<
TT,
typename boost::enable_if_c<
!boost::is_same<
TT,
typename boost::remove_cv<
typename boost::decay<TT>::type
>::type
>::value
|| boost::is_pointer<TT>::value
>::type
>
: UU<
typename boost::remove_cv<
typename boost::decay<
typename boost::remove_pointer<TT>::type
>::type
>::type
>
{};
我知道我只应该问一个问题,但我不确定如何只用一个问题表达我的困惑,所以我提前道歉。
我已经阅读了SFINAE,但是enable_if_c的模板参数令人困惑。这是否意味着如果TT与衰减的TT不同或TT是指针,那么部分模板专业化是否存在?
其次,结构继承自身意味着什么?在这种情况下,UU是否继承自UU(本身)?这是某种递归模板吗?
(代码编译时没有错误。)
答案 0 :(得分:2)
这是否意味着如果TT与衰减的TT不同或TT是指针,那么部分模板专业化是否存在?
完全。否则,替换失败,主模板用于传入的类型参数TT
。
其次,结构继承自身意味着什么?在这种情况下,UU是否继承自UU(本身)?这是某种递归模板吗?
它不会从自身继承,它继承自类模板的另一个实例。它不是真正的递归,因为通过将另一个经过修改的类型传递给它来创建其他实例化。虽然如果你认为模板是对类型进行操作的元函数,那么这确实是一个递归调用。与你在函数式编程中看到的非常相似。
这个想法是将复合类型减少为它所组成的类型。所以引用类型的引用,数组元素类型的数组和指向者类型的指针。继承允许该过程继续,直到我们手上没有复合类型。
最终,主模板检查缩减类型的正确性(在这种情况下,大小非零)。
答案 1 :(得分:0)
它继承自UU但实例化是不同的(例如,如果传递的类型是int * const *,即使在第一级指针和cv被删除后它仍然是一个指针)。但是,它确实没有传递void **(因为void参数最终将使用静态断言触发主窗体)。
答案 2 :(得分:0)
我想我现在明白了。这是一个示例模拟:
#include <boost/static_assert.hpp>
#include <boost/type_traits.hpp>
#include <boost/utility/enable_if.hpp>
#include <typeinfo>
#include <iostream>
template<class TT, typename Enable = void> struct UU { BOOST_STATIC_ASSERT_MSG(sizeof(TT) == 0, "undefined UU"); };
template<class TT>
struct UU<
TT,
typename boost::enable_if_c<
!boost::is_same<
TT,
typename boost::remove_cv<
typename boost::decay<TT>::type
>::type
>::value
|| boost::is_pointer<TT>::value
>::type
>
: UU<
typename boost::remove_cv<
typename boost::decay<
typename boost::remove_pointer<TT>::type
>::type
>::type
>
{
UU()
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};
struct dummy
{
dummy()
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};
template<>
struct UU<dummy>
{
UU()
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};
int main()
{
typedef dummy**& mytype;
std::cout << typeid(typename boost::remove_cv<typename boost::decay<mytype>::type>::type).name() << std::endl;
std::cout << boost::is_pointer<mytype>::value << std::endl;
std::cout << boost::is_same<mytype, typename boost::remove_cv<typename boost::decay<mytype>::type>::type>::value << std::endl;
UU<mytype> uu;
return 0;
}
运行时:
me@ub16:~/tmp/traits$ g++ -I~/me/bin/boost_1_60_0 c.cpp && ./a.out
PP5dummy
0
0
UU<dummy>::UU()
UU<TT, typename boost::enable_if_c<((! boost::is_same<TT, typename boost::remove_cv<typename boost::decay<T>::type>::type>::value) || boost::is_pointer<T>::value)>::type>::UU() [with TT = dummy*; typename boost::enable_if_c<((! boost::is_same<TT, typename boost::remove_cv<typename boost::decay<T>::type>::type>::value) || boost::is_pointer<T>::value)>::type = void]
UU<TT, typename boost::enable_if_c<((! boost::is_same<TT, typename boost::remove_cv<typename boost::decay<T>::type>::type>::value) || boost::is_pointer<T>::value)>::type>::UU() [with TT = dummy**; typename boost::enable_if_c<((! boost::is_same<TT, typename boost::remove_cv<typename boost::decay<T>::type>::type>::value) || boost::is_pointer<T>::value)>::type = void]
UU<TT, typename boost::enable_if_c<((! boost::is_same<TT, typename boost::remove_cv<typename boost::decay<T>::type>::type>::value) || boost::is_pointer<T>::value)>::type>::UU() [with TT = dummy**&; typename boost::enable_if_c<((! boost::is_same<TT, typename boost::remove_cv<typename boost::decay<T>::type>::type>::value) || boost::is_pointer<T>::value)>::type = void]
me@ub16:~/tmp/traits$
实例化UU<dummy**&>
时,编译器会尝试创建/定义struct UU<dummy**>
。然后它尝试创建struct UU<dummy*>
。最后,它会创建struct UU<dummy>
。
如果未定义部分模板特化,struct UU<dummy>
,则主模板的静态断言将失败:
me@ub16:~/tmp/traits$ g++ -I~/me/bin/boost_1_60_0 c.cpp && ./a.out
In file included from c.cpp:1:0:
c.cpp: In instantiation of ‘struct UU<dummy, void>’:
c.cpp:10:8: recursively required from ‘struct UU<dummy**, void>’
c.cpp:10:8: required from ‘struct UU<dummy**&>’
c.cpp:62:13: required from here
c.cpp:7:56: error: invalid application of ‘sizeof’ to incomplete type ‘boost::STATIC_ASSERTION_FAILURE<false>’
template<class TT, typename Enable = void> struct UU { BOOST_STATIC_ASSERT_MSG(sizeof(TT) == 0, "undefined UU"); };
本质上,代码的作者希望其他开发人员使用他/她的代码为每个要使用的TT定义部分模板特化template<> struct UU<TT>
。