我确信必须能够将SFINAE(可能带有宏)用于static_assert(),而仲裁代码将无法编译.
在我的代码库中有一些复杂的情况,我有一个我想禁止临时的类(我相信模式是):
class(const class&& tmp)=delete; /* deny copying from an unnamed temporary */
class (class&& rhs){/* allow construction from non-temporary rvalue*/}
Run Code Online (Sandbox Code Playgroud)
目前,我检查一个不需要的构造函数不能编译,但当然我必须将它注释掉以便再次编译测试!
如果我能做到:
static_assert(DOES_NOT_COMPILE(myclass_t("Hello")));
const char* help = "HELP";
static_assert(!DOES_NOT_COMPILE(myclass_t(help)));
// COMPILES() might be better here :-)
Run Code Online (Sandbox Code Playgroud)
这对我有很大的帮助,但我似乎无法找到一般的SFINAE解决方案.仅限C++ 14,所以:
if constexpr
Run Code Online (Sandbox Code Playgroud)
不可用.
Yak*_*ont 14
#define RETURNS(...)\
noexcept(noexcept(__VA_ARGS__))\
->decltype(__VA_ARGS__)\
{ return __VA_ARGS__;}
Run Code Online (Sandbox Code Playgroud)
这让你可以像这样写一个lambda表达式:
[](auto&&x) RETURNS( x+1 )
Run Code Online (Sandbox Code Playgroud)
要么
struct { template<class X> auto operator()(X&&x) RETURNS(x+1) };
Run Code Online (Sandbox Code Playgroud)
这是SFINAE友好的. RETURNS实际上并不是必需的,但它使得大部分代码更加清晰.有一个C++ 20的建议,以取代RETURNS与=>被SO自己@barry.
接下来,我们需要能够测试是否可以调用函数对象.
namespace details {
template<class, class, class...>
struct can_invoke:std::false_type{};
template<class F, class...Args>
struct can_invoke<
F,
std::void_t<std::result_of_t<F&&(Args&&...)>>,
Args...
>:
std::true_type
{};
}
template<class F, class...Args>
using can_invoke=details::can_invoke<F,void,Args...>;
Run Code Online (Sandbox Code Playgroud)
我们就快到了.(这是该技术的核心;我有时使用can_apply的是需要template<class...>class Z的,而不是class F在这里.) C++ 17也有类似的性状; 它可以用来代替.
test_invoke需要可调用并返回一个可调用的测试器.可调用测试器接受参数,并根据"可以使用这些参数调用原始可调用对象"返回true或false类型.
template<class F>
constexpr auto test_invoke(F&&){
return [](auto&&...args) RETURNS( can_invoke< F, decltype(args)... >{} );
}
Run Code Online (Sandbox Code Playgroud)
我们在这里. test_invoke如果你愿意使用纯类型,可以跳过,但使用值可以消除一些错误.
auto myclass_ctor=[](auto&&...args)RETURNS(myclass_t(decltype(args)(args)...));
Run Code Online (Sandbox Code Playgroud)
myclass_ctor是一个表示构造的可调用对象myclass_t.
static_assert(!test_invoke(myclass_ctor)("Hello") );
Run Code Online (Sandbox Code Playgroud)
要么
template<class C>
auto ctor=[](auto&&...args)RETURNS(C(decltype(args)(args)...));
static_assert(!test_invoke(ctor<myclass_t>)("Hello") );
Run Code Online (Sandbox Code Playgroud)
这需要constexpr lambda,一个c ++ 17功能,但是早期功能.它可以在没有它的情况下完成,但它变得丑陋.另外,移动ctor对elision的要求很烦人,可以在c ++ 14中解决.
要转换为c ++ 14,请使用具有相应constexpr特殊成员函数的手动函数对象替换每个lambda. 如上所述,同样RETURNS适用operator()于此.
为了避开elision移动ctor requrement , RETURNS(void( blah )).
为任何打扰道歉; 我在打电话.