【问题标题】:Specialized template class (descended from general case) with a template constructor using a dependent type具有使用依赖类型的模板构造函数的专用模板类(从一般情况继承)
【发布时间】:2016-02-17 16:56:34
【问题描述】:

我需要使模板类构造函数采用依赖类型(在模板类类型上)。这很好用,除非我有模板类的专门化,在这种情况下似乎找不到构造函数。而且如果我在专门的子类中重新实现构造函数,我似乎无法通过构造函数或直接初始化基类。

有没有办法在类之外保留这个相对狭窄的接口?

class T1 {};
class T2 {};

// KeyType
template <typename SELECT>
class KeyType {
};

// Declarations
template <typename SELECT = T1>
class TestTemplate {
protected:
    TestTemplate() {}
    KeyType<SELECT> k;
public:
    TestTemplate(KeyType<SELECT> const &key) : k(key) {}
};

template <>
class TestTemplate<T2> : public TestTemplate<T1> {
};


int main() {

    KeyType<T2> key;
    TestTemplate<T2> foo(key);
    return 0;
}

看了一会儿,我意识到问题是我不能随意将KeyType&lt;T2&gt; 转换为KeyType&lt;T1&gt; 用于TestTemplate&lt;T1&gt; 基类。

g++ 给出:

g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
main.cpp: In function 'int main()':
main.cpp:27:29: error: no matching function for call to 'TestTemplate<T2>::TestTemplate(KeyType<T2>&)'
     TestTemplate<T2> foo(key);
                             ^
main.cpp:20:7: note: candidate: TestTemplate<T2>::TestTemplate()
 class TestTemplate<T2> : public TestTemplate<T1> {
       ^
main.cpp:20:7: note:   candidate expects 0 arguments, 1 provided
main.cpp:20:7: note: candidate: constexpr TestTemplate<T2>::TestTemplate(const TestTemplate<T2>&)
main.cpp:20:7: note:   no known conversion for argument 1 from 'KeyType<T2>' to 'const TestTemplate<T2>&'
main.cpp:20:7: note: candidate: constexpr TestTemplate<T2>::TestTemplate(TestTemplate<T2>&&)
main.cpp:20:7: note:   no known conversion for argument 1 from 'KeyType<T2>' to 'TestTemplate<T2>&&'

【问题讨论】:

  • 如果您将TestTemplate&lt;T2&gt; 特化为从TestTemplate&lt;T1&gt; 继承,那么将KeyType&lt;T2&gt; 特化为从KeyType&lt;T1&gt; 继承可能也是有意义的。这将解决问题。
  • @StenSoft 我觉得不对,TestTemplate&lt;T2&gt; 没有接受KeyType&lt;T1&gt; const&amp; 的构造函数。

标签: c++ templates


【解决方案1】:

构造函数在 C++ 中根本不被继承,因此您的实例 TestTemplate&lt;T2&gt; 仅具有隐式声明的构造函数(默认,复制和移动它似乎是您发布的错误消息)。如果您假设,当您专门化一个模板时,专门化的模板会从被专门化的模板继承声明和定义:事实并非如此。您必须再次在您的专用模板中重新声明和重新定义所有成员。

因此,在您的情况下,您必须将适当的构造函数添加到您的专用模板中,如下所示:

template <>
class TestTemplate<T2> : public TestTemplate<T1> {
public:
    TestTemplate<KeyType<T2> const &key) :
    TestTemplate<T1>(...) {}
};

由于基类TestTemplate&lt;T1&gt; 不提供默认构造函数,因此您必须调用该构造函数,但是,不清楚您希望将什么作为关键参数传递给它,因为您有一个对KeyType&lt;T2&gt; 而不是 KeyType&lt;T1&gt; 的实例。

如果您确实希望从 TestTemplate&lt;T1&gt; 继承构造函数,则可以使用 using 指令执行此操作,假设您使用的是 C++11:

template <>
class TestTemplate<T2> : public TestTemplate<T1> {
public:
    using TestTemplate<T1>::TestTemplate;
};

但不可否认,我并不是 100% 了解这里的语法。

【讨论】:

    猜你喜欢
    • 2021-07-26
    • 2016-03-04
    • 1970-01-01
    • 2018-09-29
    • 2019-12-14
    • 2014-12-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多