问题描述
我理解模板成员函数只有在使用时才会生成。如果不是所有使用的类型都支持这样的功能,这是方便的。然而,这似乎不适用于具有尾部返回类型规范的函数。下面是一个小实验:
$ $
$ bcode>,具有适当的成员函数 f , g 。
但是,如果我尝试实例化 S< int> ,例如由 S< int> s {}; ,我会得到像类型的错误类型'int'不是一个结构或联合。这发生在尝试调用模板函数 f1 , g1 的两种情况 T (或非模板函数 g int )。即使我不是试图在对象 s上调用 f1 或 g1 code>。然而,GCC在 g1 的情况下很好; Clang不是。
案例A(模板成员函数 f )的解决方法是使用辅助函数 F ,这是 f2 的行为,并适用于Clang和GCC。它看起来工作,因为调用 T()。template f< A>()从 f2 ,并且当类型 A 未知时,编译器不在 F (T()) 。
对于情况B(非模板成员函数 g )的相同解决方法也适用于两个编译器。
我会感激一些帮助,找出发生了什么。在每种情况下都是正确的行为?哪个编译器是正确的?一般来说还有其他解决方法吗?
我使用GCC 4.8.1和Clang 3.3。
解决方案SFINAE仅适用于函数的模板参数,而不适用于继承自该类的模板参数。
T到第二个模板参数,但这只是您的解决方法的更短版本:
#include< utility&
#include< type_traits>
struct Foo {
template<类型名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必须等于T ;
return TT()。template f< A>();
}
};
int main(){
S< Foo>一个;
a.f1< int>(); // ok
S< int> b;
b.f1< int>(); // not ok
}
I understand that template member functions are only generated if used. This is convenient if not all used types support such a function. However, this does not appear to work for functions with trailing return type specification. Below is a small experiment:
// 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()); } };Please keep in mind that this sample is only meant to illustrate the issue, it is not useful in anything else.
S <T> can be instantiated for any type T that has appropriate member functions f, g.
However, if I try to instantiate S <int>, e.g. by S <int> s{};, I do get errors like type 'int' is not a structure or union. This happens for both cases f1, g1, which attempt to call template function f or non-template function g respectively on a value of type T (int in this case). It happens even though I am not trying to call f1 or g1 on object s. However, GCC is fine with the case of g1; Clang is not.
A workaround for case A (template member function f) is to use a helper function F, which is what f2 does, and works fine for both Clang and GCC. It appears to work because call T().template f <A>() is hidden from the declaration of f2, and the compiler is not looking into F <A>(T()) when type A is unknown.
The same workaround for case B (non-template member function g) is also working for both compilers.
I would appreciate some help in finding out what is going on. Which is the correct behaviour in each case? Which compiler is correct? Is there any other workaround in general?
I am using GCC 4.8.1 and Clang 3.3.
解决方案SFINAE only applies to the template arguments of the function, not the one inherited from the class.
A different solution is to include copy T to a second template argument but this is nothing more than a shorter version of your workaround:
#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 }
这篇关于模板成员函数具有尾部返回类型,即使未使用也会产生错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!