以下代码是最低工作(或可能是非工作)的示例。
它的作用基本上是将一堆std :: map结构封装为基类中的私有成员。为避免编写大量的setter和getter,它们被实现为模板函数。
// test.cpp
#include <map>
#include <iostream>
enum class E0
{
F0, F1, F2,
};
基类的声明。
using std::map;
class P_base
{
private:
map<E0, int> m_imap;
// ...
// ... Other std::map members with different key types and value types.
public:
map<E0, int> & imap;
// ...
// ... Other std::map references.
P_base() : imap(m_imap) {}
template<typename map_type, typename key_type, typename val_type>
void set(map_type & m, const key_type & k, const val_type & v)
{
m[k] = v;
}
template<typename map_type, typename key_type>
auto access_to_map(const map_type & m, const key_type & k) -> decltype(m.at(k))
{
return m.at(k);
}
};
class P : private P_base
{
public:
decltype(P_base::imap) & imap;
P() : P_base(), imap(P_base::imap) {}
template<typename map_type, typename key_type, typename val_type>
void set(map_type & m, const key_type & k, const val_type & v)
{
P_base::set(m, k, v);
}
template<typename map_type, typename key_type>
auto access_to_map(const map_type & m, const key_type & k) -> decltype(P_base::access_to_map(m, k))
{
return P_base::access_to_map(m, k);
}
};
主
int main(int argc, const char * argv[])
{
using std::cout;
using std::endl;
P op;
op.set(op.imap, E0::F0, 100);
op.set(op.imap, E0::F1, 101);
op.set(op.imap, E0::F2, 102);
cout << op.access_to_map(op.imap, E0::F1) << endl;
}
$ clang++ -std=c++11 test.cpp && ./a.out
101
但是如果我使用intel编译器(icpc版本15.0.3(gcc版本5.1.0兼容性))编译它,编译器会给我这个错误消息(我根本不会这样做,特别是当clang编译时代码):
$ icpc -std=c++ test.cpp && ./a.out
test.cpp(67): error: no instance of function template "P::access_to_map" matches the argument list
argument types are: (std::__1::map<E0, int, std::__1::less<E0>, std::__1::allocator<std::__1::pair<const E0, int>>>, E0)
object type is: P
cout << op.access_to_map(op.imap, E0::F1) << endl;
这也让我感到困惑的是没有抱怨设置功能。</ p>
有谁知道这里发生了什么?
答案 0 :(得分:2)
注意:我的回答适用于g ++ - 希望它与icc相同。
这是一个较小的测试用例:
struct Base
{
int func(int t) { return t; }
};
struct Der : Base
{
template<typename T>
auto f(T t) -> decltype(Base::func(t))
{
return t;
}
};
int main(){ Der d; d.f(5); }
错误是:
mcv.cc: In function 'int main()':
mcv.cc:16:25: error: no matching function for call to 'Der::f(int)'
int main(){ Der d; d.f(5); }
^
mcv.cc:16:25: note: candidate is:
mcv.cc:9:7: note: template<class T> decltype (t->Base::func()) Der::f(T)
auto f(T t) -> decltype(Base::func(t))
^
mcv.cc:9:7: note: template argument deduction/substitution failed:
mcv.cc: In substitution of 'template<class T> decltype (t->Base::func()) Der::f(T) [with T = int]':
mcv.cc:16:25: required from here
mcv.cc:9:38: error: cannot call member function 'int Base::func(int)' without object
auto f(T t) -> decltype(Base::func(t))
可以通过将decltype(Base::func(t))
更改为decltype(this->Base::func(t))
来解决此问题。对我来说,相应的修复程序会修复您的代码示例。
显然,编译器并不认为应该使用Base::func(t)
作为隐藏参数调用*this
。我不知道这是一个g ++错误,还是因为clang超出了职责范围。
请注意,在C ++ 14中,由于函数只有一个return语句,因此可以完全省略尾随返回类型:
template<typename T>
auto f(T t)
{
return t;
}