我有一个实现某些功能的基类,以及一个实际上扩展它的模板类。基类有一个非默认构造函数,因为它需要一些配置数据。该模板有一个默认构造函数。
class Base
{
public:
explicit Base(int data): m_data{data} {}
int boilerplate(int x) const { return x + m_data; }
protected:
int m_data;
};
template<typename T>
class Test: public virtual Base
{
public:
virtual int foo(T x) const { return x + m_data; } // works by default for integers for convenience
};
我正在尝试创建一个继承自模板的多个专业化的类,它可以将相同的数据传递给单个虚拟基类。
class MultiTest : public Test<float>, public Test<double>
{
public:
int foo(float x) const override { return x * static_cast<float>(boilerplate(3)); }
int foo(double x) const override { return x / static_cast<double>(boilerplate(10)); }
};
如果我使用整数参数实例化该类,则会收到错误:
int main() { MultiTest x{32}; }
$ g++ test.cpp
test.cpp: In function ‘int main()’:
test.cpp:24:26: error: no matching function for call to ‘MultiTest::MultiTest(<brace-enclosed initializer list>)’
24 | int main() { MultiTest x{32}; }
| ^
test.cpp:17:7: note: candidate: ‘MultiTest::MultiTest(const MultiTest&)’
17 | class MultiTest : public Test<float>, public Test<double>
| ^~~~~~~~~
test.cpp:17:7: note: no known conversion for argument 1 from ‘int’ to ‘const MultiTest&’
test.cpp:17:7: note: candidate: ‘MultiTest::MultiTest(MultiTest&&)’
test.cpp:17:7: note: no known conversion for argument 1 from ‘int’ to ‘MultiTest&&’
我不能做
int main() { MultiTest x; } with no arguments either of course, since the
Base`类没有默认构造函数:
$ g++ test.cpp
test.cpp: In function ‘int main()’:
test.cpp:24:24: error: use of deleted function ‘MultiTest::MultiTest()’
24 | int main() { MultiTest x; }
| ^
test.cpp:17:7: note: ‘MultiTest::MultiTest()’ is implicitly deleted because the default definition would be ill-formed:
17 | class MultiTest : public Test<float>, public Test<double>
| ^~~~~~~~~
test.cpp:17:7: error: use of deleted function ‘Test<float>::Test()’
test.cpp:11:7: note: ‘Test<float>::Test()’ is implicitly deleted because the default definition would be ill-formed:
11 | class Test: public virtual Base
| ^~~~
test.cpp:11:7: error: no matching function for call to ‘Base::Base()’
test.cpp:4:14: note: candidate: ‘Base::Base(int)’
4 | explicit Base(int data): m_data{data} {}
| ^~~~
test.cpp:4:14: note: candidate expects 1 argument, 0 provided
test.cpp:1:7: note: candidate: ‘constexpr Base::Base(const Base&)’
1 | class Base
| ^~~~
test.cpp:1:7: note: candidate expects 1 argument, 0 provided
test.cpp:1:7: note: candidate: ‘constexpr Base::Base(Base&&)’
test.cpp:1:7: note: candidate expects 1 argument, 0 provided
test.cpp:17:7: error: use of deleted function ‘Test<double>::Test()’
17 | class MultiTest : public Test<float>, public Test<double>
| ^~~~~~~~~
test.cpp:11:7: note: ‘Test<double>::Test()’ is implicitly deleted because the default definition would be ill-formed:
11 | class Test: public virtual Base
| ^~~~
test.cpp:11:7: error: no matching function for call to ‘Base::Base()’
test.cpp:4:14: note: candidate: ‘Base::Base(int)’
4 | explicit Base(int data): m_data{data} {}
| ^~~~
test.cpp:4:14: note: candidate expects 1 argument, 0 provided
test.cpp:1:7: note: candidate: ‘constexpr Base::Base(const Base&)’
1 | class Base
| ^~~~
test.cpp:1:7: note: candidate expects 1 argument, 0 provided
test.cpp:1:7: note: candidate: ‘constexpr Base::Base(Base&&)’
test.cpp:1:7: note: candidate expects 1 argument, 0 provided
test.cpp:17:7: error: no matching function for call to ‘Base::Base()’
17 | class MultiTest : public Test<float>, public Test<double>
| ^~~~~~~~~
test.cpp:4:14: note: candidate: ‘Base::Base(int)’
4 | explicit Base(int data): m_data{data} {}
| ^~~~
test.cpp:4:14: note: candidate expects 1 argument, 0 provided
test.cpp:1:7: note: candidate: ‘constexpr Base::Base(const Base&)’
1 | class Base
| ^~~~
test.cpp:1:7: note: candidate expects 1 argument, 0 provided
test.cpp:1:7: note: candidate: ‘constexpr Base::Base(Base&&)’
test.cpp:1:7: note: candidate expects 1 argument, 0 provided
如果我尝试在
Base
中添加对 MultiTest
构造函数的调用,例如与explicit MultiTest(int data): Base{data} {}
发生类似的事情:
$ g++ test.cpp
test.cpp: In constructor ‘MultiTest::MultiTest(int)’:
test.cpp:20:44: error: use of deleted function ‘Test<float>::Test()’
20 | explicit MultiTest(int data): Base{data} {}
| ^
test.cpp:11:7: note: ‘Test<float>::Test()’ is implicitly deleted because the default definition would be ill-formed:
11 | class Test: public virtual Base
| ^~~~
test.cpp:11:7: error: no matching function for call to ‘Base::Base()’
test.cpp:4:14: note: candidate: ‘Base::Base(int)’
4 | explicit Base(int data): m_data{data} {}
| ^~~~
test.cpp:4:14: note: candidate expects 1 argument, 0 provided
test.cpp:1:7: note: candidate: ‘constexpr Base::Base(const Base&)’
1 | class Base
| ^~~~
test.cpp:1:7: note: candidate expects 1 argument, 0 provided
test.cpp:1:7: note: candidate: ‘constexpr Base::Base(Base&&)’
test.cpp:1:7: note: candidate expects 1 argument, 0 provided
test.cpp:20:44: error: use of deleted function ‘Test<double>::Test()’
20 | explicit MultiTest(int data): Base{data} {}
| ^
test.cpp:11:7: note: ‘Test<double>::Test()’ is implicitly deleted because the default definition would be ill-formed:
11 | class Test: public virtual Base
| ^~~~
test.cpp:11:7: error: no matching function for call to ‘Base::Base()’
test.cpp:4:14: note: candidate: ‘Base::Base(int)’
4 | explicit Base(int data): m_data{data} {}
| ^~~~
test.cpp:4:14: note: candidate expects 1 argument, 0 provided
test.cpp:1:7: note: candidate: ‘constexpr Base::Base(const Base&)’
1 | class Base
| ^~~~
test.cpp:1:7: note: candidate expects 1 argument, 0 provided
test.cpp:1:7: note: candidate: ‘constexpr Base::Base(Base&&)’
test.cpp:1:7: note: candidate expects 1 argument, 0 provided
我也尝试过
explicit MultiTest(int data): Test<float>{data}, Test<double>{data} {}
:
$ g++ test.cpp
test.cpp: In constructor ‘MultiTest::MultiTest(int)’:
test.cpp:20:71: error: no matching function for call to ‘Base::Base()’
20 | explicit MultiTest(int data): Test<float>{data}, Test<double>{data} {}
| ^
test.cpp:4:14: note: candidate: ‘Base::Base(int)’
4 | explicit Base(int data): m_data{data} {}
| ^~~~
test.cpp:4:14: note: candidate expects 1 argument, 0 provided
test.cpp:1:7: note: candidate: ‘constexpr Base::Base(const Base&)’
1 | class Base
| ^~~~
test.cpp:1:7: note: candidate expects 1 argument, 0 provided
test.cpp:1:7: note: candidate: ‘constexpr Base::Base(Base&&)’
test.cpp:1:7: note: candidate expects 1 argument, 0 provided
test.cpp:20:71: error: no matching function for call to ‘Test<float>::Test(<brace-enclosed initializer list>)’
20 | explicit MultiTest(int data): Test<float>{data}, Test<double>{data} {}
| ^
test.cpp:11:7: note: candidate: ‘Test<float>::Test(const Test<float>&)’
11 | class Test: public virtual Base
| ^~~~
test.cpp:11:7: note: no known conversion for argument 1 from ‘int’ to ‘const Test<float>&’
test.cpp:11:7: note: candidate: ‘Test<float>::Test(Test<float>&&)’
test.cpp:11:7: note: no known conversion for argument 1 from ‘int’ to ‘Test<float>&&’
test.cpp:20:71: error: no matching function for call to ‘Test<double>::Test(<brace-enclosed initializer list>)’
20 | explicit MultiTest(int data): Test<float>{data}, Test<double>{data} {}
| ^
test.cpp:11:7: note: candidate: ‘Test<double>::Test(const Test<double>&)’
11 | class Test: public virtual Base
| ^~~~
test.cpp:11:7: note: no known conversion for argument 1 from ‘int’ to ‘const Test<double>&’
test.cpp:11:7: note: candidate: ‘Test<double>::Test(Test<double>&&)’
test.cpp:11:7: note: no known conversion for argument 1 from ‘int’ to ‘Test<double>&&’
并获得了类似的结果
explicit MultiTest(int data): Test<float>{data}, Test<double>{data}, Base{data} {}
:
$ g++ test.cpp
test.cpp: In constructor ‘MultiTest::MultiTest(int)’:
test.cpp:20:83: error: no matching function for call to ‘Test<float>::Test(<brace-enclosed initializer list>)’
20 | explicit MultiTest(int data): Test<float>{data}, Test<double>{data}, Base{data} {}
| ^
test.cpp:11:7: note: candidate: ‘Test<float>::Test(const Test<float>&)’
11 | class Test: public virtual Base
| ^~~~
test.cpp:11:7: note: no known conversion for argument 1 from ‘int’ to ‘const Test<float>&’
test.cpp:11:7: note: candidate: ‘Test<float>::Test(Test<float>&&)’
test.cpp:11:7: note: no known conversion for argument 1 from ‘int’ to ‘Test<float>&&’
test.cpp:20:83: error: no matching function for call to ‘Test<double>::Test(<brace-enclosed initializer list>)’
20 | explicit MultiTest(int data): Test<float>{data}, Test<double>{data}, Base{data} {}
| ^
test.cpp:11:7: note: candidate: ‘Test<double>::Test(const Test<double>&)’
11 | class Test: public virtual Base
| ^~~~
test.cpp:11:7: note: no known conversion for argument 1 from ‘int’ to ‘const Test<double>&’
test.cpp:11:7: note: candidate: ‘Test<double>::Test(Test<double>&&)’
test.cpp:11:7: note: no known conversion for argument 1 from ‘int’ to ‘Test<double>&&’
我需要对
MultiTest
或 main
做什么才能使这项工作成功?还有,为什么?
您需要提供一些额外的构造函数:
template<typename T>
class Test: public virtual Base
{
public:
explicit Test (int data) : Base (data) { } // <==
virtual int foo(T x) const { return x + m_data; } // works by default for integers for convenience
};
和:
class MultiTest : public Test<float>, public Test<double>
{
public:
explicit MultiTest (int data) : Base (data), Test <float> (data), Test <double> (data) { } // <==
int foo(float x) const override { return x * static_cast<float>(boilerplate(3)); }
int foo(double x) const override { return x / static_cast<double>(boilerplate(10)); }
};
顺便说一句,我不能说我很喜欢整个想法。