模板成员函数具有尾随返回类型,即使未使用也会出现错误
Template member functions with trailing return type, giving errors even if unused
我知道模板成员函数只有在使用时才会生成。如果不是所有使用的类型都支持这样的功能,那么这很方便。然而,这似乎不适用于具有尾随返回类型规范的函数。下面是一个小实验:
// helper function for case A workaround
template <typename A, typename T>
auto F(T&& x)
-> decltype(x.template f <A>())
{ return x.template f <A>(); }
// helper function for case B workaround
template <typename A, typename T>
auto G(T&& x)
-> decltype(x.g())
{ return x.g(); }
template <typename T>
struct S
{
// case A: not ok in GCC + Clang
template <typename A>
auto f1()
-> decltype(T().template f <A>())
{ return T().template f <A>(); }
// case A workaround: ok in Clang + GCC
template <typename A>
auto f2()
-> decltype(F <A>(T()))
{ return F <A>(T()); }
// case B: ok in GCC, not ok in Clang
template <typename A>
auto g1()
-> decltype(T().g())
{ return T().g(); }
// case B workaround: ok in GCC + Clang
template <typename A>
auto g2()
-> decltype(G <A>(T()))
{ return G <A>(T()); }
};
请记住,这个样本只是为了说明这个问题,它在其他任何方面都没有用处。
S <T>
可以被实例化用于具有适当的成员函数f
、g
的任何类型的T
。
然而,如果我尝试实例化S <int>
,例如通过S <int> s{};
,我确实会得到类似type 'int' is not a structure or union
的错误。对于两种情况f1
和g1
都会发生这种情况,它们试图分别对类型为T
的值调用模板函数f
或非模板函数g
(在这种情况下为int
)。即使我没有尝试在对象s
上调用f1
或g1
,也会发生这种情况。然而,对于g1
的情况,GCC是好的;Clang不是。
情况A(模板成员函数f
)的一个变通方法是使用辅助函数F
,f2
就是这样做的,并且对Clang和GCC都很好。它似乎可以工作,因为调用T().template f <A>()
在f2
的声明中是隐藏的,并且当类型A
未知时,编译器不会查看F <A>(T())
。
对于情况B(非模板成员函数g
),同样的解决方法也适用于这两个编译器。
如果能帮我弄清楚发生了什么,我将不胜感激。在每种情况下,哪种行为是正确的?哪个编译器是正确的?一般来说,还有其他变通方法吗?
我使用的是GCC 4.8.1和Clang 3.3。
SFINAE仅适用于函数的模板参数,而不适用于从类继承的模板参数。
一个不同的解决方案是将T复制到第二个模板参数中,但这只不过是一个较短版本的变通方法:
#include <utility>
#include <type_traits>
struct Foo {
template < typename T > T f() { return {}; }
};
template <typename T>
struct S {
template <typename A, typename TT = T >
auto f1() -> decltype(std::declval<TT>().template f <A>()) {
static_assert(std::is_same<T,TT>::value, "TT must be equal to T" );
return TT().template f <A>();
}
};
int main() {
S<Foo> a;
a.f1<int>(); // ok
S<int> b;
b.f1<int>(); // not ok
}
相关文章:
- VC++ C2011 重定义错误 - 未使用的头文件
- 编译错误:"error_category"未使用 g++ 6.3.0 命名类型"
- 未使用模板类型定义的同时参数包扩展错误
- 错误:未使用不完整的类型'struct std::hash<>'无效
- 将升压actor_lexer转换为静态:错误,好像"actor_"未使用
- 在.c文件接收函数中使用Linux中的MSGGET创建消息队列未实现错误
- C++:错误:成员访问不完整的类型,未使用的参数[-Werror,-Wunused-parameter]
- cmake错误未使用Xcode和GLFW找到CMAKE_C_COMPILER
- 模板成员函数具有尾随返回类型,即使未使用也会出现错误
- 映射未声明:首次在函数中使用错误
- 如何构建使用 OpenCV 的 XCode 6 iOS 应用程序 - 未定义错误__cplusplus
- C++:使用错误 C4700 未初始化的局部变量""
- 未使用调试器标志编译的代码出现分段错误
- 未使用的变量错误,或者应该是错误
- "Undefined symbols for Architecture x86_64 "未使用模板,可能存在语法错误
- C++内存:删除未使用的布尔数组可以将结果从正确更改为错误
- 为什么未使用的部分专业化没有错误
- 无法解决 Qt/C++/NMake 的链接器错误 - 未使用选项 '/LIBPATH:' 指定参数 (Qt 5.2.0/MSVC 2010)
- Makefile错误-链接器输入文件未使用
- 如何调用函数和未使用的表达式错误