模板类的模板函数专门化

Kos*_*nov 9 c++ templates template-specialization c++11 c++14

是否可以在C++ 11/14中编写类似的内容?

#include <iostream>
#include <vector>

template <typename T>
T Get();

template <typename T>
struct Data {
    std::vector<T> data;
};

template <>
template <typename T>
Data<T> Get<Data<T>>() {
    return Data<T>{{T{}, T{}}};
}

template <>
template <typename T>
std::vector<T> Get<std::vector<T>>() {
    return std::vector<T>(3);
}

int main() {
    std::cout << Get<Data<int>>().data.size() << std::endl;  // expected output is 2
    std::cout << Get<std::vector<int>>().size() << std::endl; // expected output is 3
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,重载将无济于事,因为调用Get<...>()将是不明确的(请参阅参考资料):

template <typename T>
Data<T> Get() {
    return Data<T>{{T{}, T{}}};
}

template <typename T>
std::vector<T> Get() {
    return std::vector<T>(3);
}
Run Code Online (Sandbox Code Playgroud)

关于如何克服这个问题的任何方向都是受欢

Mat*_*jek 7

有一个解决方法,它给你这样的东西:不专门 - 重载:

#include <iostream>
#include <vector>
#include <string>

using namespace std;

template <typename T>
size_t Get(const T& data)
{
    return 444;
}

template <typename T>
struct Data
{
    std::vector<T> data;
};

template <typename T>
size_t Get(const Data<T>& data) {
    return data.data.size();
}

int main() {
    std::cout << Get<>(0) << std::endl;  // expected output is 444
    std::cout << Get<>(Data<int>{}) << std::endl;  // expected output is 0
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

444
0
Run Code Online (Sandbox Code Playgroud)

注意,这size_t Get(const Data<T>& data)不是一个特殊化 - 它完全是"不同的" Get(),它被称为Data<T>任何类型的参数T.

在这里你可以看到工作样本.


编辑

我看到你完全改变了你的问题.但是,我仍然会尝试回答它.缺少部分函数专业化有一个标准的解决方法 - 使用委托给结构/类.

这是你需要的:

#include <iostream>
#include <vector>

using namespace std;

template <typename T>
struct GetImpl;

template <typename T>
struct Data {
    std::vector<T> data;
};

template <typename T>
struct GetImpl< Data<T> >
{
    static Data<T> Get() {
        return Data<T>{ {T{}, T{}} };
    };
};

template <typename T>
struct GetImpl< std::vector<T> >
{
    static std::vector<T> Get() {
        return std::vector<T>(3);
    };
};

int main() {
    std::cout << GetImpl< Data<int> >::Get().data.size() << std::endl;  // expected output is 2
    std::cout << GetImpl< std::vector<int> >::Get().size() << std::endl; // expected output is 3
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

2
3
Run Code Online (Sandbox Code Playgroud)

工作样本可以在这里找到.


如果您不喜欢语法,可以通过将静态函数更改Get()为函数调用运算符来使其更短一些:

template <typename T>
struct Get< Data<T> >
{
    Data<T> operator()() {
        return Data<T>{ {T{}, T{}} };
    };
};

template <typename T>
struct Get< std::vector<T> >
{
    std::vector<T> operator()() {
        return std::vector<T>(3);
    };
};
Run Code Online (Sandbox Code Playgroud)

然后:

Get< Data<int> >()().data.size();
Get< std::vector<int> >()().size();
Run Code Online (Sandbox Code Playgroud)

你只有两个额外的角色 - ().这是我能想到的最短的解决方案.

  • *"不,你不能称之为Get <Data <int >>()"*,ekhm ... [你可以](http://coliru.stacked-crooked.com/a/b7b5421ea28e05b7),@ KostyaBazhanov仅供参考 (3认同)

Ben*_*igt 5

正如Columbo在他的评论中提到的那样,您应该应用标准的解决方法,因为缺少对函数的部分特化支持:委派给部分专门的类:

template <typename T>
struct GetImpl;

template <typename T>
T Get() { return GetImpl<T>::Do(); }
Run Code Online (Sandbox Code Playgroud)

现在使用部分特化struct GetImpl<T> { static T Do(); }而不是Get<T>()