考虑这个例子:
#include <iostream>
#include <type_traits>
template <class, class = void>
struct is_defined : std::false_type
{ };
template <class T>
struct is_defined<T,
std::enable_if_t<std::is_object<T>::value &&
!std::is_pointer<T>::value
>
> : std::true_type
{
private:
static const T test; //try to create incomplete type member
};
struct defined { };
struct forward_declared;
int main()
{
std::cout << std::boolalpha
<< is_defined<defined>::value << std::endl
<< is_defined<forward_declared>::value << std::endl;
}
两者的输出均为true
。我想如果我尝试使struct
成员不完整,那么这个模板特化将从重载集中丢弃。但事实并非如此。删除static const
会导致不完整类型的编译时错误。这种方法有什么问题,如果可能的话,怎么能实现呢?
答案 0 :(得分:11)
试试这个:
SELECT * FROM
(
select
n.ArticleID, n.Title, n.ArticleImage, cl.CategoryName
from
News as n
inner join
Categories as c on n.ArticleID = c.ArticleID
inner join
CategoryList as cl on cl.CategoryID = c.CategoryID
where cl.CategoryName = 'Hot'
group by
n.ArticleID, n.Title, n.ArticleImage, cl.CategoryName
) AS A
INNER JOIN
(
select
n.ArticleID, n.Title, n.ArticleImage, cl.CategoryName
from
News as n
inner join
Categories as c on n.ArticleID = c.ArticleID
inner join
CategoryList as cl on cl.CategoryID = c.CategoryID
where cl.CategoryName = 'New'
group by
n.ArticleID, n.Title, n.ArticleImage, cl.CategoryName
) AS B ON A.ArticleID = B.ArticleID
答案 1 :(得分:4)
一般情况下,在这种情况下,您可以使用一些不接受不完整类型的操作符来表示您的sfinae表达式。
例如,您可以使用typeid
:
#include <iostream>
#include <type_traits>
#include <utility>
template<typename T, typename = void>
constexpr bool is_defined = false;
template<typename T>
constexpr bool is_defined<T, decltype(typeid(T), void())> = true;
struct defined { };
struct forward_declared;
int main()
{
std::cout << std::boolalpha
<< is_defined<defined> << std::endl
<< is_defined<forward_declared> << std::endl;
}
正如其他人所说,另一个有效运算符是sizeof
。
答案 2 :(得分:1)
关于问题“这种方法有什么问题......” 当我们进行静态const T检验时;它不是is_defined&lt; ...&gt;的一部分我们实际上必须在其他地方定义静态成员is_defined&lt; ...&gt; :: test,并且只在那个“else”的地方我们需要T来完成类型。 is_defined&LT; ...&GT; class编译只是因为静态成员大小对is_defined&lt; ...&gt;没有影响大小
去除静态const会导致T检验;成为is_defined&lt; ...&gt;的成员(并且要影响is_defined&lt; ...&gt;大小)因此T必须是完整类型才能具有已知大小。
更新注释:如果在模板专业化中声明类成员,SFINAE不会因为这也不是“参数替换”,也不是“SFINAE表达式”(也不是功能要超载!)。相反,它是某种“SFINAE字段声明” - 在替换失败的情况下,标准不是“非错误”。