C ++ Dummy模板参数在派生模板类中使用typedef时导致错误

时间:2017-12-17 03:17:33

标签: c++ templates c++17 modularity

我试图修复一个奇怪的错误,我正在使用此代码。这是一个可以复制错误的最小示例:

test11.cpp

namespace detail{
   template <auto UInt>
   class Test{
      public:
         typedef decltype(UInt) value_type;

         Test (const value_type& x = 0);

      protected:
         value_type n;
   };

   template<auto UInt>
   Test<UInt>::Test (const value_type& x) : n(x){}

   // Here, void would be substitute with some enable_if stuff
   template <auto UInt, typename = void>
   class TestChild : public Test<UInt>{
      public:
         typedef typename Test<UInt>::value_type value_type;

         TestChild (const value_type& x = 0);
         value_type foo() const;
   };

   template<auto UInt>
   TestChild<UInt>::TestChild (const value_type& x) : Test<UInt>(x){}

   template<auto UInt>
   value_type TestChild<UInt>::foo(){
      value_type ret=42;
      return ret;
   }
}

int main(){}

我在Ubuntu 16.04 LTS中使用GCC 7.2.0和Clang 5.0.0编译它。你可以看到这两个演示链接:

gcc中的错误消息是:

test11.cpp:27:38: error: ‘value_type’ does not name a type
    TestChild<UInt>::TestChild (const value_type& x) : Test<UInt>(x){}
                                      ^~~~~~~~~~
test11.cpp:27:51: error: invalid use of incomplete type ‘class detail::TestChild<UInt>’
    TestChild<UInt>::TestChild (const value_type& x) : Test<UInt>(x){}
                                                   ^
test11.cpp:18:10: note: declaration of ‘class detail::TestChild<UInt>’
    class TestChild : public Test<UInt>{
          ^~~~~~~~~
test11.cpp:30:4: error: ‘value_type’ does not name a type
    value_type TestChild<UInt>::foo(){
    ^~~~~~~~~~

另外,对我来说真的很奇怪的是,如果我在类TestChild的模板中省略了伪参数(我的意思是,template<auto UInt>而不是template<auto UInt, typename = void>) ,我仍然得到一个(更短的)错误,看起来像这样:

test11.cpp:30:4: error: ‘value_type’ does not name a type
    value_type TestChild<UInt>::foo(){
    ^~~~~~~~~~

您可以查看GCC 7.2.0 here的演示。

看起来主要的错误是,如果我在课外定义函数,typedef typename Test<UInt>::value_type value_type;没有被真正检测到(我不知道我是否自己解释得很好)。 / p>

如果在我定义类中的函数时也会发生这种情况,这对我来说很有意义,但事实并非如此,因为在最后一种情况下一切都很好(你可以在{{3中看到它)如果你愿意的话。)

总之,我的主要问题是我想编译这个程序,但请记住,我必须将声明与定义分开。所以我展示的最后一个演示(其中所有内容都在类中定义)是我想要实现的,但是模块化。

我希望有人可以帮助我并解释这段代码的用途。

1 个答案:

答案 0 :(得分:2)

您应该进行三次(至少)更改。

首先:为TestChild添加第二个(默认)模板值。

所以

//................vvvvvvvvvvvv
template<auto UInt, typename V>
TestChild<UInt, V>::TestChild (const value_type& x) : Test<UInt>(x){}
//............^^^

foo()方法相同

第二:请记住foo()const

所以

template <auto UInt, typename V>
value_type TestChild<UInt, V>::foo() const {
   value_type ret=42;  // ...........^^^^^
   return ret;
}

第三:对于foo()明确的类

的返回类型

所以typename TestChild<UInt, V>::value_type代替value_type

template <auto UInt, typename V>
typename TestChild<UInt, V>::value_type TestChild<UInt, V>::foo() const {
   value_type ret=42;
   return ret;
}

或者,如果您愿意,可以使用auto ... ->返回类型语法

template<auto UInt, typename V>
auto TestChild<UInt, V>::foo() const -> value_type {
   value_type ret=42;
   return ret;
}

或简称auto(但也在方法声明中)

auto foo() const;

// ...

template<auto UInt, typename V>
auto TestChild<UInt, V>::foo() const {
   value_type ret=42;
   return ret;
}