Vin*_*ent 2 c++ lambda sfinae template-meta-programming c++14
请考虑以下代码:
// -------------------------------------------------------------------------- //
// Preprocessor
#include <array>
#include <vector>
#include <utility>
#include <iostream>
#include <type_traits>
// -------------------------------------------------------------------------- //
// -------------------------------------------------------------------------- //
// Calls a function without arguments if it can be called
template <
class F,
class... Args,
class = decltype(std::declval<F>()())
>
decltype(auto) apply(F&& f)
{
std::cout<<"apply(F&& f)"<<std::endl;
return std::forward<F>(f)();
}
// Calls a function with arguments if it can be called
template <
class F,
class Arg,
class... Args,
class = decltype(std::declval<F>()(
std::declval<Arg>(), std::declval<Args>()...
))
>
decltype(auto) apply(F&& f, Arg&& arg, Args&&... args)
{
std::cout<<"apply(F&& f, Arg&& arg, Args&&... args)"<<std::endl;
return std::forward<F>(f)(
std::forward<Arg>(arg),
std::forward<Args>(args)...
);
}
// Does nothing if the function cannot be called with the given arguments
template <
class F,
class... Args
>
void apply(F&& f, Args&&... args)
{
std::cout<<"apply(F&& f, Args&&... args)"<<std::endl;
}
// -------------------------------------------------------------------------- //
// -------------------------------------------------------------------------- //
// Main function
int main(int argc, char* argv[])
{
// Initialization
auto f = [](auto&& x) -> decltype(std::forward<decltype(x)>(x).capacity()) {
return std::forward<decltype(x)>(x).capacity();
};
auto g = [](auto&& x) -> decltype(auto) {
return std::forward<decltype(x)>(x).capacity();
};
auto h = [](auto&& x) {
return std::forward<decltype(x)>(x).capacity();
};
// Test
apply(f, std::vector<double>()); // -> sfinae works
apply(g, std::vector<double>()); // -> sfinae works
apply(h, std::vector<double>()); // -> sfinae works
apply(f, std::array<double, 1>());// -> sfinae works
//apply(g, std::array<double, 1>()); -> sfinae fails, does not compile
//apply(h, std::array<double, 1>()); -> sfinae fails, does not compile
// Return
return 0;
}
// -------------------------------------------------------------------------- //
Run Code Online (Sandbox Code Playgroud)
该实用程序apply在可以编译时将参数应用于参数,否则它什么都不做.该机制依赖于sfinae.然而,对于函数,其返回类型从主体推导,如g与h在上述例子中,SFINAE失败.在C++ 14中是否有一种聪明的方法来修改apply实用程序,这样即使对于从主体推断出返回类型的函数,它也会强制使用sfinae?
注意:我想制作g和h工作f,意思是调用apply应该调用void版本.
SFINAE只能捕获替代错误.
调用函数时的一些错误不能是替换错误.这些包括解析函数体时发生的错误.
C++明确选择将这些错误排除在触发SFINAE之外,而是触发硬错误,使编译器不必编译任意函数体来确定是否发生SFINAE.由于SFINAE必须在重载解析期间完成,这使得C++编译器的重载解析代码更容易.
如果您希望您的代码对SFINAE友好,则不能使用lambdas g或者h.
| 归档时间: |
|
| 查看次数: |
238 次 |
| 最近记录: |