在下面的代码中,我试图用一个函子来调用它作为参数的任何东西,“无论什么”是一组有限的选项(这里的两个不是我代码中唯一的选项)。
#include <memory>
#include <iostream>
template<class T>
struct call_with_pointer {
// last resort: T*
template<class Callable>
static auto call(Callable &callable, const std::shared_ptr<T> ¶m) -> decltype(callable(param.get())) {
return callable(param.get());
}
};
template<class T>
struct call_with_shared : public call_with_pointer<T> {
// best: call with shared_ptr<T>.
// SFINA
// error: Candidate template ignored: substitution failure [with Callable = Test]: no matching function for call to object of type 'Test'
template<class Callable>
static auto call(Callable &callable, const std::shared_ptr<T> ¶m) -> decltype(callable(param)) {
return callable(param);
}
using call_with_pointer<T>::call;
};
class Test {
public:
bool operator () (int * x) {
return *x == 42;
}
};
int main ()
{
Test t;
auto i = std::make_shared<int>(4);
auto x = call_with_shared<int>::call(t, i); // No matching function for call to 'call'
return 0;
}
此代码在VS和GCC中运行良好。不幸的是,它没有铿锵作响。错误消息是:
没有用于调用'call'的匹配函数
忽略了候选模板:替换失败[使用Callable = Test]:没有匹配函数 调用'Test'类型的对象
因此它忽略了使用智能指针的候选者。好。但它似乎没有继续考虑继承的调用可以正常工作。
问题:我该如何解决这个问题?我怎样才能让llvm在这里做正确的事?
答案 0 :(得分:2)
尝试以下方法:
template<class T>
struct call_with_pointer {
// last resort: T*
template<class Callable>
static auto call(Callable &callable, const std::shared_ptr<T> ¶m) -> decltype(callable(param.get())) {
return callable(param.get());
}
};
template<class T>
struct call_with_pointer_2 {
// last resort: T*
template<class Callable>
static auto call(Callable &callable, const std::shared_ptr<T> ¶m) -> decltype(callable(param)) {
return callable(param);
}
};
template<class T>
struct call_with_shared : public call_with_pointer<T>, public call_with_pointer_2<T>{
using call_with_pointer<T>::call;
using call_with_pointer_2<T>::call;
};
答案 1 :(得分:1)
严格来说,clang是正确的,因为C ++ 11的7.3.3p15(继承函数模板的using声明被忽略,因为它与派生类的成员函数模板具有相同的名称和参数)。虽然很明显该段在不考虑这些非冲突声明时存在缺陷。
您可以使用typename YieldFirstType<std::shared_ptr<T>, Callable>::type
之类的内容作为其中一个模板中的第二个参数类型来处理它。