我使用一个带有不同参数的函数的(C)库,但在出现错误时总是返回大于零的int:
int functionA(int param1, char param2); /* return an error code on failure, 0 otherwise */
int functionB(LIB_BOOLEAN param1); /* return an error code on failure, 0 otherwise */
// ...
我想把它们全部变为异常准备好了:
if (functionA(param1, param2) > 0)
{ throw std::runtime_error("Method failed"); }
是否有可能为所有方法编写模板一次?
编辑: 我们的想法是每次使用时都避免检查每个函数的结果。
答案 0 :(得分:6)
你的意思是这样吗?
template<typename F, typename... Args>
auto my_invoke(F &&f, Args&&... args) {
if(std::forward<F>(f)(std::forward<Args>(args)...)) {
throw std::runtime_error("Method failed");
}
}
您可以将其称为;
my_invoke(functionA, 0, 'c');
答案 1 :(得分:2)
以下是使用C ++ 17的新auto
模板参数的基于模板的解决方案:
template <auto &> struct CallerImpl;
template <typename ...Args, int (&F)(Args ...)>
struct CallerImpl<F>
{
static int CallOrThrow(Args ... args)
{
if (int n = F(args...); n > 0)
throw std::runtime_error("Method failed");
else
return n;
}
};
template <auto & F, typename ... Brgs>
int CallOrThrow(Brgs ... brgs)
{
return CallerImpl<F>::CallOrThrow(brgs...);
}
用法示例:
int foo(double, char)
{
std::cout << "Foo called\n";
return 8;
}
CallOrThrow<foo>(1.5, 'x');
答案 2 :(得分:2)
我知道我会因此而被投票,但老实说,我认为这是一个可以有效使用预处理器的案例:
#define CHECK( fn ) \
{ \
if( fn > 0 ) { \
throw "problem"; \
} \
}
int f(int x) {
return x - 1;
}
int main() {
CHECK( f(42) );
}
很明显,它很简单,很简单,可以使用__LINE__
,__FILE__
和其他预定义的宏,而这些宏不能用于模板。
答案 3 :(得分:1)
#!/bin/bash
i=1
c=1
options=()
while [ $c -gt 0 ]
do
v=$(phpbrew list | sed -n "${i}p")
if [ -z "$v" ]; then
c=0
elif [ -n "$v" ]; then
options+=("$v")
fi
i=$[$i+1]
done
count=0
printf "\n"
echo 'Available versions:'
for i in "${options[@]}"
do
echo "$i $[$count+1]"
count=$[$count+1]
done
printf "\n"
echo 'Which version should be enabled?'
read selected
chosen="${options[$selected - 1]}"
chosen="$(echo -e "${chosen}" | tr -d '[:space:]')"
chosen="$(echo -e "${chosen}" | sed 's/\*//g')"
chosen="$(echo -e "${chosen}" | sed 's/php-//g')"
echo -e "php-${chosen} to be enabled."
source $HOME/.phpbrew/bashrc
phpbrew switch php-${chosen}
if [[ $chosen =~ ^5 ]]; then
sudo a2dismod php7
sudo a2enmod php5
sudo service apache2 reload
elif [[ $chosen =~ ^7 ]]; then
sudo a2dismod php5
sudo a2enmod php7
sudo service apache2 reload
else echo 'This script only works on php 5 and 7';
fi
未经测试,但这样的事情应该有效。
希望它有所帮助!
答案 4 :(得分:1)
这是一种不需要更改呼叫站点的方法。假设这些C函数对返回代码都有相同的约定,您可以编写一个将返回代码转换为异常的包装器。
inline void checked(const char *name, int result) {
if (result > 0)
throw std::runtime_error(name);
}
然后为每个函数引入预处理器定义。
#define functionA(...) checked("functionA", functionA(__VA_ARGS__))
这是有效的,因为functionA
不会在functionA
宏的定义中展开。从C ++ 11开始,可变参数宏是标准的。