C++ 只有在需要时才可以缩小范围吗?
假设我有以下代码,其中C++ 只有在需要时才可以缩小范围吗?,c++,guideline-support-library,C++,Guideline Support Library,假设我有以下代码,其中bar是在另一个库中定义的: void bar(int x); /* this declaration comes from some included header file */ void foo(long long y) { return bar(y); } 为了使故障可检测,GSL指示我使用GSL::shorrow,如下所示: void bar(int x); /* this declaration comes from some included
bar
是在另一个库中定义的:
void bar(int x); /* this declaration comes from some included header file */
void foo(long long y)
{
return bar(y);
}
为了使故障可检测,GSL指示我使用GSL::shorrow
,如下所示:
void bar(int x); /* this declaration comes from some included header file */
void foo(long long y)
{
return bar(narrow<int>(y));
}
所有这些都可以存在于gsl
名称空间中,我只需将我的函数编写为:
void foo(long long x)
{
return superint_visit(bar, superint{x});
}
即使我在这里接受了一个答案,我仍然希望听到任何人谁可以使上述发生 对于这个问题,已经发布了非常好的创造性解决方案。但是它们都有依赖于库实现的问题——例如,如果存在条重载,那么客户端代码就无法编译 在我看来,在这种情况下,bar的客户真正想要的是: “我想使用接受一个特定积分参数的条,如果存在其他重载,则与此无关” 与库无关的非内在直接方法也是最简单的一种方法——一种带有积分参数的细棒包装器。这样,它不依赖于任何库实现细节:
void bar(int x); /* this declaration comes from some included header file */
template <typename T, typename = std::enable_if_v<std::is_integral_v<T>>>
inline void mybar(T x)
{
// express directly which bar overload you want to use here
bar(narrow<int>(x)); // <- the only place you need to ajudst if bar interface changes, btw. use the overload from bar which you really want
}
void foo(long long y)
{
return mybar(y); // use mybar instead of bar within your code
}
void bar(int x);/*此声明来自一些包含的头文件*/
模板
内联无效mybar(T x)
{
//在此处直接表示要使用哪个条重载
bar(窄(x));//您没有bar
?没问题。只需为x
获取decltype
。这可以通过为整个函数获取decltype
,并编写模板来恢复参数类型:
template <typename>
struct argType;
template <typename R, typename A>
struct argType<R(A)>
{
using type = A;
};
void foo(long long y)
{
bar(narrow<typename argType<decltype(bar)>::type>(y));
}
模板
结构argType;
模板
结构argType
{
使用类型=A;
};
void foo(长y)
{
酒吧(窄(y));
}
您可以利用以下事实:重载解析有利于非模板函数与函数模板的完美参数类型匹配:
#include <iostream>
// (A)
void bar(int y) { std::cout << "bar(int)\n"; }
// (B)
//void bar(long long) { std::cout << "bar(long long)\n"; }
// (C)
template <typename T>
void bar(T) = delete;
// (C.SP1)
template<>
void bar<long long>(long long y) { bar(narrow<int>(y)); }
int main() {
long long a = 12LL;
bar(a); // bar(int)
// bar(long long) if `bar(long long)` above is available.
}
获取第一个参数的类型可以使用
具有所有参数的类型,然后可以使用
#包括
空心条(int-y);
void foo(长y)
{
酒吧(窄(y));
}
将bar作为模板如何?这样您就可以调用bar(y)并在bar实现中做出所有与大小相关的决策。对于其客户来说,bar应该能够处理任何整数类型。我认为这是您基本上想要的。不是我的library@stPierence解决方案。但在每次调用bar时都需要编写这些内容的可读性不是很高。也许可以在cust中添加一个级别的间接寻址om功能将更加强大appropriate@StPiere您可以通过typedef或在typetypename argType::type
上使用来缩短它,我想知道std中是否已经有一个很好的解决方案,比如它可能会给出返回值为bar的type。@basheba,当然,那会更好。人们只需要在每次调用什么类型时知道狭义的cast应该是cast。我个人觉得从设计的角度来看这很奇怪,但这不是问题的主题。但还是很好。我的意思是,如果库也有void bar(char)
,你就不能使用bar
的类型,当添加void bar(long-long)
时,代码也会无法编译(允许删除变通方法:)。但是如果void bar(long-long)
替换void bar(int)
,它将编译(让变通方法就位)。很好,但这可能会破坏库中的重载解析,具体取决于您何时将模板重载呈现给编译器。@Bathsheba是的,很好。我想您可以为bar
添加一个公共包装,并将重载解析委派放在定义包装的TU中,为添加的bar
重载。这与对另一个答案的评论中的限制相同:库中不应存在其他bar
重载,未来的bar(long-long)
重载必须取代bar(int)
one.Nice。这是使用Boost时优雅的结果。+1。
#include <iostream>
// (A)
void bar(int y) { std::cout << "bar(int)\n"; }
// (B)
//void bar(long long) { std::cout << "bar(long long)\n"; }
// (C)
template <typename T>
void bar(T) = delete;
// (C.SP1)
template<>
void bar<long long>(long long y) { bar(narrow<int>(y)); }
int main() {
long long a = 12LL;
bar(a); // bar(int)
// bar(long long) if `bar(long long)` above is available.
}
// foo.h
#pragma once
void foo(long long y);
// foo.cpp
#include "foo.h"
#include "gsl/gsl_narrow"
#include "the_lib/bar.h"
namespace {
template <typename T>
void bar(T) = delete;
template<>
void bar<long long>(long long y) { bar(narrow<int>(y)); }
} // namespace
void foo(long long y) {
bar(y);
}
#include <boost/callable_traits/args.hpp>
void bar(int y);
void foo(long long y)
{
bar(narrow<std::tuple_element<0, boost::callable_traits::args_t<decltype(bar)>>::type>(y));
}