这个语法正确吗?

3

当我取消注释下面的main()代码行时,Visual Studio 2015无法编译(在其他情况下可以编译代码)。

#include <iostream>
#include <type_traits>

template <typename Output, std::size_t... Input> struct RemoveLastHelper;

template <template <std::size_t...> class Z, std::size_t... Accumulated, std::size_t First, std::size_t... Rest>
struct RemoveLastHelper<Z<Accumulated...>, First, Rest...> :
    RemoveLastHelper<Z<Accumulated..., First>, Rest...> {};

template <template <std::size_t...> class Z, std::size_t... Accumulated, std::size_t Last>
struct RemoveLastHelper<Z<Accumulated...>, Last> {
    using type = Z<Accumulated...>;
};

template <template <std::size_t...> class Z, std::size_t... Is>
using RemoveLast = RemoveLastHelper<Z<>, Is...>;

struct Base {
    virtual ~Base() = default;
    virtual void foo() const = 0;
};

template <std::size_t... Is> struct Derived;

template <std::size_t R>
struct Derived<R> : public Base {
    virtual void foo() const override {}
};

// For example, Derived<R,D1,D2,D3> inherits from Derived<R,D1,D2>, which inherits from
// Derived<R,D1>, which inherits from Derived<R>, which inherits from Base (by the above).
template <std::size_t R, std::size_t... Is>
struct Derived<R, Is...> : public RemoveLast<Derived, R, Is...>::type {
    virtual void foo() const override {RemoveLast<Derived, R, Is...>::type::foo();}
};

int main() {
//  Derived<0,2,1> r;  // This line won't compile.
}

它出现了错误:
'Derived<0,2>': invalid template argument for template parameter 'Z', expected a class template
'RemoveLast': left of '::' must be a class/struct/union
'type': is not a class or namespace name

那么问题出在哪里呢?GCC 5.1可以编译它,但我不知道那是否只是偶然。这个语法 virtual void foo() const override {RemoveLast<Derived, R, Is...>::type::foo();} 合法吗?如果不合法,我应该如何实现它(我只是想调用它的基类foo()函数)。如果它是合法的,我应该如何重写它,以便Visual Studio可以接受它(我需要它能在Visual Studio上工作)?
1个回答

5
这很简单。将Derived替换为Derived::template Derived即可。
template <std::size_t R, std::size_t... Is>
struct Derived<R, Is...> : public RemoveLast<Derived, R, Is...>::type {
    virtual void foo() const override {RemoveLast<Derived::template Derived, R, Is...>::type::foo();}
};

::Derived 也可以使用。这似乎是Clang和Visual Studio中存在的注入类名bug。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接