我试图修复一个奇怪的错误,我正在使用此代码。这是一个可以复制错误的最小示例:
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中看到它)如果你愿意的话。)
总之,我的主要问题是我想编译这个程序,但请记住,我必须将声明与定义分开。所以我展示的最后一个演示(其中所有内容都在类中定义)是我想要实现的,但是模块化。
我希望有人可以帮助我并解释这段代码的用途。
答案 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;
}