仅当函数支持传递合适的可变参数时才编译
Compiling only if function supports passed suitable variadic arguments
#include <iostream>
#include <utility>
class A
{
public:
void run(int value)
{
std::cout << value << std::endl;
}
};
class B
{
public:
void run(int value1, int value2)
{
std::cout << value1 << " "
<< value2
<< std::endl;
}
};
template<typename T,
typename ... Args>
void call_run(T& t, Args&& ... args)
{
// scope below should compile only
// if T has a run function and
// this run function has a signature
// matching Args
// (empty score otherwise)
{
t.run(std::forward<Args>(args)...);
}
}
int main()
{
int value = 1;
A a;
call_run(a,value);
// compilation error if uncommented
//B b;
//call_run(b,value);
return 0;
}
上面的代码可以正常编译和运行。
但是如果最新的部分,用 B 的实例调用 call_run,没有注释,代码编译失败,原因很明显:
main.cpp:34:9: error: no matching function for call to ‘B::run(int&)’
t.run(std::forward<Args>(args)...);
是否可以忽略不适用的范围进行编译? (此处忽略意味着在编译时用空范围替换有缺陷的范围)
从 c++17 开始你可以使用 if constexpr
:
if constexpr (std::is_invocable_v<decltype(&T::run),T*,Args...>)
{
t.run(std::forward<Args>(args)...);
}
invocable 在编译时检查,如果它 returns 为假,if 作用域的主体将被忽略。
#include <iostream>
#include <utility>
class A
{
public:
void run(int value)
{
std::cout << value << std::endl;
}
};
class B
{
public:
void run(int value1, int value2)
{
std::cout << value1 << " "
<< value2
<< std::endl;
}
};
template<typename T,
typename ... Args>
void call_run(T& t, Args&& ... args)
{
// scope below should compile only
// if T has a run function and
// this run function has a signature
// matching Args
// (empty score otherwise)
{
t.run(std::forward<Args>(args)...);
}
}
int main()
{
int value = 1;
A a;
call_run(a,value);
// compilation error if uncommented
//B b;
//call_run(b,value);
return 0;
}
上面的代码可以正常编译和运行。 但是如果最新的部分,用 B 的实例调用 call_run,没有注释,代码编译失败,原因很明显:
main.cpp:34:9: error: no matching function for call to ‘B::run(int&)’
t.run(std::forward<Args>(args)...);
是否可以忽略不适用的范围进行编译? (此处忽略意味着在编译时用空范围替换有缺陷的范围)
从 c++17 开始你可以使用 if constexpr
:
if constexpr (std::is_invocable_v<decltype(&T::run),T*,Args...>)
{
t.run(std::forward<Args>(args)...);
}
invocable 在编译时检查,如果它 returns 为假,if 作用域的主体将被忽略。