是否可以将模板专用化建立在方法签名中是否存在某个参数的基础上
Is it possible to base the template specialization on the presence or absence of a certain argument in the method signature?
考虑以下类:
class MyClass
{
public:
template<class T> typename T::result_type apply(T& func)
{
if (is_int())
{
return func(int(0));
}
return func(double(0));
}
...
};
(代码看起来并不是很有用,但它只是一个人为的示例来证明我的观点)
无论如何,一个典型的函子应该是这样的:
struct MyFunc
{
typedef void result_type;
template<class V> void operator()(V)
{
// do something
}
};
人们会这样使用它:
MyClass c;
MyFunc f;
c.apply(f);
我的问题是,MyClass::apply
是否可以更改为识别除原始版本之外稍有不同的函子版本,例如,期望调用方对象引用与所有其他参数一起传递的版本,类似于以下内容:
struct MyFuncEx
{
typedef void result_type;
template<class V> void operator()(const MyClass& caller, V)
{
// do something
}
};
因此,以下代码也将编译:
MyClass c;
MyFunc f;
c.apply(f);
MyFuncEx f2;
c.apply(f2);
额外的一点是,如果函数同时包含两个重载,我希望编译失败,即以下内容应使编译失败:
struct MyFuncSmartAss
{
typedef void result_type;
template<class V> void operator()(V)
{
// do something
}
template<class V> void operator()(const MyClass& caller, V)
{
// do something
}
};
...
MyClass c;
c.apply(MyFuncSmartAss());
但是,只要较长的过载优先于较短的过载,就没有那么重要。
这实际上取决于您是否拥有C++11。这应该解决C++11中的过载问题(*):
class MyClass {
private:
int _int;
double _double;
public:
template <typename F>
auto apply(F& f) -> decltype(f(_int), f(_double)) {
if (is_int()) { return f(_int); }
return f(_double);
}
template <typename F>
auto apply(F& f) -> decltype(f(*this, _int), f(*this, _double)) {
if (is_int()) { return f(*this, _double); }
return f(_double)
}
};
它是如何工作的?
- 删除不合适的重载:带有
decltype
的尾部返回类型规范创建了一个未赋值的上下文。编译器执行表达式的常规重载解析,但只关心类型。如果发生错误(operator()
在f
中不存在),则我们命中SFINAE,并丢弃apply
的此过载 - 如果两者都有效,则歧义:如果两个重载都合适(因为
F
同时提供两个运算符),则调用是歧义的
(*)我不太确定尾部返回类型规范的正确性,更具体地说,this
和_arg
的使用。Clang 3.0和gcc 4.5.2都出现错误。这是可以解决的,只是变得更详细一点。
// first
decltype(f(0), f(0.0))
// second
decltype(f(std::declval<MyClass>(), 0), f(std::declval<MyClass>(), 0.0))
在ideone上使用此解决方法:
- 没有可能的功能
- 选择合适的过载
- 避免了模棱两可的呼叫
编辑:以满足int/double
的要求
相关文章:
- 这个极客对极客的trie实现是否存在内存泄漏问题
- 如何检查QList中是否存在值
- 根据某个函数是否存在启用模板
- 地图计数确实很重要,或者只是检查是否存在
- C++中是否存在 std::conditional 的懒惰等价物?
- 无论如何,我可以确定构造函数是否存在吗?
- COM :是否可以查看是否存在对我的某个 COM 对象的进程外引用?我可以释放它吗?
- 堆分配的对象是否存在永不为空的唯一所有者?
- 扩展类中的可选 vir 函数,测试它在运行时是否存在
- 模板化检查是否存在带有参数列表的类成员函数?
- 是否存在包含负号的isdigit函数(过载)
- 如何巧妙地编写两个函数——一个用于检查是否存在解决方案,另一个用于获取所有解决方案
- 检查编译时是否存在静态函数
- 向量是否存在行主要形式?
- 检查 TinyXML 中的元素是否存在
- 检测是否存在具有 C++17 的类成员
- 虚拟继承中是否存在多重继承?
- 我遇到了这个代码片段,不明白. 它递归检查 C++ 字符串中是否存在大写字符
- std::weak_ptr 和相应的 std::shared_ptr 之间是否存在数据竞争?
- 是否存在用于 C 或 C++ 中常见数学运算(例如最小值、最大值和平均值)的可导入库?