【问题标题】:Class template as parameter in a template specializationa类模板作为模板特化中的参数a
【发布时间】:2014-06-21 16:47:21
【问题描述】:

是否可以在模板特化中使用类模板作为参数?

我希望能够使用foo<Foo<int>>() 之类的东西(请参阅源代码中的#3)并为该模板实例运行具有唯一代码。目前只有普通的专业化工作(见#2)。

以前的similar question 会让我相信#3 的方法会起作用,但代码至少在 msvc2012 下不起作用。

我正在尝试做的事情可能吗?如果有,怎么做?

来源

// Test struct.
template<class T>
struct Foo
{
    T foo;
};

// #1 Ordinary template
template<class T>
T foo()
{
    return T();
}

// #2 Template specialization
template<>
int foo<int>()
{
    return 42;
}

// #3 Template specialization with template as parameter? Not working.
template<>
template<typename T>
Foo<T> foo<Foo<T>>()
{
    return Foo<T>();
}

【问题讨论】:

  • Clang 对额外的typename&lt;&gt; 给出了很好的清晰警告。无论如何,您不能部分专门化功能模板。但是您可以部分专门化类模板。
  • 我同意,这不适用于函数。总结一下
  • "模板类"正确的术语是类模板。它是生成类的模板。
  • 感谢您的信息,从现在开始我将其称为“类模板”。

标签: c++ templates template-specialization


【解决方案1】:

函数不能部分特化,需要封装成类或结构体

#include <iostream>
using namespace std;

// Test struct.
template<class T>
struct Foo
{
    T foo;
};

// Struct specialization
template<>
struct Foo<bool>
{
    static const int val = 46;
};

// #1 Ordinary template
template<class T>
struct functionWrapper {
    static T foo() {
        return T();
    }
};

// #2 Template specialization
template<>
struct functionWrapper<int> {
    static int foo() {
        return 42;
    }
};

// #3 Template specialization with template as parameter
template<class T>
struct functionWrapper<struct Foo<T>> {
    static Foo<T>* foo() {
        return new Foo<T>();
    }
};

int main() {
    cout << functionWrapper<bool>::foo() << endl;
    cout << functionWrapper<int>::foo() << endl;

    Foo<bool> *obj = functionWrapper<Foo<bool>>::foo();
    cout << obj->val;
    delete obj; // Always be a good citizen

    return 0;
}

http://ideone.com/8TXJH4

【讨论】:

  • 感谢您的解决方案。但是,我有点困惑为什么类模板的行为应该与函数模板不同。我希望在未来的 C++ 版本中改变它。
  • 另外,我发现在堆上分配 Foo 有点不必要。但我确实想成为一个好公民。 :)
  • @Adelost 在堆上分配它只是我做出的一个决定,“没有想太多”让样本工作。您可以根据需要更改它,但请注意您使用/返回的对象的范围(以及如果您将它们复制到目标中)。至于功能部分专业化 AFAIK,标准决定不支持它们,因为它们会引入额外的复杂性和内在问题(谷歌搜索 Dimov/Abrahams 问题,你会得到我所说的示例)。
【解决方案2】:

我重写了 Marco A. 的解决方案,以允许我保留原始语法。

然后,我还提出了第二种解决方案,它使用“输出参数”而不是“返回值”。我认为这个解决方案更好,因为它维护和完成相同的工作更简单。

解决方案 #1(用原始语法重写 Marco A 的解决方案)

#include <iostream>
using namespace std;

// Test struct
template<class T>
struct Foo
{
    T foo;
};

// #1 Ordinary template
template<class T>
struct FooWrapper
{
    static T foo()
    {
        return T();
    }
};

// #2 Template specialization
template<>
struct FooWrapper<int>
{
    static int foo()
    {
        return 42;
    }
};

// #3 Template specialization with template as parameter
template<class T>
struct FooWrapper<Foo<T>>
{
    static Foo<T> foo()
    {
        return Foo<T>();
    }
};

// Hides wrapper implementation
template<class T>
T foo()
{
    return FooWrapper<T>::foo();
}

int main()
{
    cout << foo<bool>() << endl;
    cout << foo<int>() << endl;
    cout << foo<Foo<int>>().foo << endl;

    return 0;
}

解决方案 #2(更简单,使用 out 参数可能更好的解决方案)

#include <iostream>
using namespace std;

// Test struct
template<class T>
struct Foo
{
    T foo;
    int bar;
};

// #1 General case
template<class T>
void foo(T& value)
{
    value = T();
}

// #2 Special case
void foo(int& value)
{
    value = 2;
}

// #3 Special case with class template
template<class T>
void foo(Foo<T>& value)
{
    value.bar = 3;
}

// Function templates with hidden specializations
template<class T>
T foo()
{
    T value;
    foo(value);

    return value;
}

int main()
{
    cout << foo<bool>() << endl;
    cout << foo<int>() << endl;
    cout << foo<Foo<int>>().bar << endl;

    return 0;
}

【讨论】:

    猜你喜欢
    • 2011-05-10
    • 2018-11-26
    • 2018-06-25
    • 1970-01-01
    • 2015-02-19
    • 2012-12-07
    • 1970-01-01
    • 2023-03-12
    • 2017-02-03
    相关资源
    最近更新 更多