非依赖名称方案中的模板基类上的名称查找

时间:2018-10-03 16:14:15

标签: c++

以以下代码为例:

template <typename T>
struct foo_base
{
    void doit(T*) {}
};

template <typename T>
struct foo : foo_base<T> {};

template <typename T>
struct get_result
{
    template <typename Result>
    static Result GetType(void (T::*)(Result*));

    using type = decltype(GetType(&T::doit));
};

int main()
{
    std::cout << typeid(typename get_result<foo<int>>::type).name() << '\n';
}

此代码将无法同时使用GCC和Clang进行编译,但可以使用MSVC成功进行编译。 c给出的错误是:

<source>:21:27: error: use of undeclared identifier 'GetType'
    using type = decltype(GetType(&T::doit));
                          ^
<source>:26:34: note: in instantiation of template class 'get_result<foo<int> >' requested here
    std::cout << typeid(typename get_result<foo<int>>::type).name() << '\n';
                                 ^
<source>:19:19: note: must qualify identifier to find this declaration in dependent base class
    static Result GetType(void (T::*)(Result*));
                  ^

通常,当涉及到一致性时,我会支持GCC / Clang,尤其是当他们俩都同意的时候,但是我不能确切地说明原因。实例化get_result<foo<int>>时,它也应该实例化foo_base<int>,所以我认为表达式T::doit应该编译没有问题。

FWIW解决方法相当简单:

template <typename Type, typename Result>
static Result GetType(void (Type::*)(Result*));

1 个答案:

答案 0 :(得分:1)

&foo<int>::doit实际上是&foo_base<int>::doit

因此其类型为void (foo_base<int>::*)(int*),但是GetType期望使用类型为void (foo<int>::*)(T*)的参数,因此无法推论T