Mik*_*ail 16 c++ boost compiler-errors sfinae c++11
简而言之:
如何编写测试,检查我的类是不可复制的还是可复制的,但只能移动并可移动分配?
一般来说:
如何编写测试,确保特定代码不编译?像这样:
// Movable, but non-copyable class
struct A
{
A(const A&) = delete;
A(A&&) {}
};
void DoCopy()
{
A a1;
A a2 = a1;
}
void DoMove()
{
A a1;
A a2 = std::move(a1);
}
void main()
{
// How to define these checks?
if (COMPILES(DoMove)) std::cout << "Passed" << std::endl;
if (DOES_NOT_COMPILE(DoCopy)) std::cout << "Passed" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
我想与SFINAE有关,但有一些现成的解决方案,也许是在提升?
Yak*_*ont 18
template<class T>struct sink{typedef void type;};
template<class T>using sink_t=typename sink<T>::type;
template<typename T, typename=void>struct my_test:std::false_type{};
template<typename T>struct my_test<T,
sink_t<decltype(
Run Code Online (Sandbox Code Playgroud)
把代码放在这里.请注意,它必须"早期失败",即在函数的签名中,而不是在正文中
)>
>:std::true_type {};
Run Code Online (Sandbox Code Playgroud)
如果可以评估"在这里放置代码",则上面生成测试.
要确定是否无法评估"此处放置代码",请取消测试结果.
template<class T>using not_t=std::integral_constant<bool, !T::value>;
not_t< my_test< int > >::value
Run Code Online (Sandbox Code Playgroud)
如果"在这里放置代码"在替换阶段失败,那将是真的.(或者你可以通过交换std::true_type
和std::false_type
上面的方式更多地手动完成).
在替换阶段失败不同于一般失败,因为它必须是一个表达,你在某些方面受限制.但是,要测试是否可以复制,您可以执行以下操作:
template<typename T, typename=void>struct copy_allowed:std::false_type{};
template<typename T>struct copy_allowed<T,
sink_t<decltype(
T( std::declval<T const&>() )
)>
>:std::false_type {};
Run Code Online (Sandbox Code Playgroud)
并移动:
template<typename T, typename=void>struct move_allowed:std::false_type{};
template<typename T>struct move_allowed<T,
sink_t<decltype(
T( std::declval<T>() )
)>
>:std::false_type {};
Run Code Online (Sandbox Code Playgroud)
并且只移动:
template<typename T>struct only_move_allowed:
std::integral_constant<bool, move_allowed<T>::value && !copy_allowed<T>::value >
{};
Run Code Online (Sandbox Code Playgroud)
上面的一般技术依赖于SFINAE.基本特征类看起来像:
template<class T, typename=void> struct whatever:std::false_type{};
Run Code Online (Sandbox Code Playgroud)
在这里,我们采用一种类型T
,以及我们默认的第二个(匿名)参数void
.在一个工业强度库中,我们将其隐藏为实施细节(公共特征将转向这种私人特征.
然后我们专注.
template<typename T>struct whatever<T, /*some type expression*/>:std::true_type{};
Run Code Online (Sandbox Code Playgroud)
诀窍在于,当且仅当我们希望我们的测试通过时,我们/*some type expression*/
才对类型进行评估void
.如果失败,我们可以评估为非void
类型,或者只是发生替换失败.
当且仅当它评估void
我们得到true_type
.
在sink_t<
某些类型的表达>
技术利用任何类型的表达,并将其转化void
:基本上它是用于取代发生故障的测试. sink
在图论中,指的是一个物质流入的地方,没有任何东西出现 - 在这种情况下,void
什么都没有,并且类型流入它.
对于类型表达式,我们使用decltype(
一些非类型表达式)
,它允许我们在"假"上下文中对它进行评估,我们只是抛弃结果.现在仅针对SFINAE目的评估非类型表达式.
请注意,MSVC 2013对此特定步骤的支持有限或不支持.他们称之为"表达SFINAE".必须使用替代技术.
非类型表达式的类型得到评估.它实际上并没有运行,并且它不会导致ODR使用任何东西.所以我们可以std::declval<X>()
用来生成一个类型的"假"实例X
.我们使用X&
了左值,X
为右值,并X const&
为const
左值.
Andrzej Krzemie\xc5\x84ski 的一篇精彩文章“可诊断的有效性”的末尾给出了一个很好的答案:
\n\n\n\n检查给定构造是否无法编译的一种实用方法是从 C++ 外部执行此操作:准备一个带有错误构造的小型测试程序,对其进行编译,然后测试编译器是否报告编译失败。这就是 \xe2\x80\x9cnegative\xe2\x80\x9d 单元测试与 Boost.Build 一起工作的方式。有关示例,请参阅此否定测试表单 Boost.Optional 库:Optional_test_fail_convert_from_null.cpp。在配置文件中它被注释为compile-fail,意味着只有编译失败时测试才通过。
\n
归档时间: |
|
查看次数: |
2511 次 |
最近记录: |