在派生模板中使用 typedef 时,C++ 虚拟模板参数引发错误 class
C++ Dummy template parameter inducing error while using a typedef in derived template class
我正在尝试修复我在使用此代码时遇到的一个奇怪错误。这是一个可以复制错误的最小示例:
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(){
^~~~~~~~~~
此外,对我来说真正奇怪的是,如果我在 class 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。
看起来主要的错误是,如果我在 class 之外定义函数,typedef typename Test<UInt>::value_type value_type;
并没有被真正检测到(我不知道我是否解释清楚了) .
如果我在 class 中定义函数时也会发生这种情况,这对我来说是有意义的,但事实并非如此,因为在最后一种情况下一切都可以正常编译(您可以在 demo 如果你愿意的话)。
总之,我的主要问题是我想编译这个程序,但要记住我必须将声明与定义分开。所以我展示的最后一个演示(所有内容都在 class 内定义)是我想要实现的,但是模块化。
我希望有人能帮助我并解释这段代码是怎么回事。
您应该(至少)进行三处更改。
首先:为 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;
}
第三:对于return类型对于foo()
显式class
所以 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 ... ->
return 类型语法
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;
}
我正在尝试修复我在使用此代码时遇到的一个奇怪错误。这是一个可以复制错误的最小示例:
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(){
^~~~~~~~~~
此外,对我来说真正奇怪的是,如果我在 class 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。
看起来主要的错误是,如果我在 class 之外定义函数,typedef typename Test<UInt>::value_type value_type;
并没有被真正检测到(我不知道我是否解释清楚了) .
如果我在 class 中定义函数时也会发生这种情况,这对我来说是有意义的,但事实并非如此,因为在最后一种情况下一切都可以正常编译(您可以在 demo 如果你愿意的话)。
总之,我的主要问题是我想编译这个程序,但要记住我必须将声明与定义分开。所以我展示的最后一个演示(所有内容都在 class 内定义)是我想要实现的,但是模块化。
我希望有人能帮助我并解释这段代码是怎么回事。
您应该(至少)进行三处更改。
首先:为 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;
}
第三:对于return类型对于foo()
显式class
所以 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 ... ->
return 类型语法
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;
}