kfc*_*ckf 15 c++ templates member-functions template-specialization c++17
我有一个模板类和一个成员函数print()来打印数据。
template<typename T>
class A
{
public:
T data;
void print(void)
{
std::cout << data << std::endl;
}
// other functions ...
};
Run Code Online (Sandbox Code Playgroud)
然后,我想打印标量数据或矢量数据,所以我给出了一个专门的定义并得到一个编译器错误。
template<typename T>
void A<std::vector<T>>::print(void) // template argument list error
{
for (const auto& d : data)
{
std::cout << d << std::endl;
}
}
Run Code Online (Sandbox Code Playgroud)
问题:为什么这个成员函数特化会报错?为向量定义打印函数的正确方法是什么?
解决方案 1:我已经测试了以下定义。
template<typename T>
class A<std::vector<T>>
{
public:
std::vector<T> data;
void print(void) { // OK
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
这个有效,但我必须将其他成员函数复制到这个专门的类中。
编辑:
解决方案2:为了防止复制所有其他成员函数,我定义了一个包含公共成员函数的基类并从基类继承:
template<typename T>
class Base
{
public:
T data;
// other functions ...
};
template<typename T>
class A : public Base<T>
{
public:
void print(void)
{
std::cout << this->data << std::endl;
}
};
template<typename T>
class A<std::vector<T>> : public Base<std::vector<T>>
{
public:
void print(void)
{
for (const auto& d : this->data)
{
std::cout << d << std::endl;
}
}
};
Run Code Online (Sandbox Code Playgroud)
此解决方案效果很好。有没有更好或更传统的解决方案?
JeJ*_*eJo 10
为什么这个成员函数专业化会出错?
A例如A<std::vector<int>>,当您实例化模板类时,模板参数T等于std::vector<int>,不是std::vector<T>,这是函数的特化情况。不幸的是,这不能用评论中提到的成员函数来完成。
有没有更好的解决方案?
是的;在c++17 中,您可以使用if constexprtrait 来检查std::vector,就像这样。
#include <type_traits> // std::false_type, std::true_type
#include <vector>
// traits for checking wether T is a type of std::vector<>
template<typename T> struct is_std_vector final : std::false_type {};
template<typename... T> struct is_std_vector<std::vector<T...>> final : std::true_type {};
template<typename T>
class A /* final */
{
T mData;
public:
// ...constructor
void print() const /* noexcept */
{
if constexpr (is_std_vector<T>::value) // when T == `std::vector<>`
{
for (const auto element : mData)
std::cout << element << "\n";
}
else // for types other than `std::vector<>`
{
std::cout << mData << std::endl;
}
}
};
Run Code Online (Sandbox Code Playgroud)
(见在线直播)
这样你只保留一个模板类,并且print()会T在编译时根据模板类型实例化适当的部分。
如果您无权访问 C++17,另一种选择是SFINAE成员(自c++11 起)。
#include <type_traits> // std::false_type, std::true_type, std::enbale_if
#include <vector>
// traits for checking wether T is a type of std::vector<>
template<typename T> struct is_std_vector final : std::false_type {};
template<typename... T> struct is_std_vector<std::vector<T...>> final : std::true_type {};
template<typename T>
class A /* final */
{
T mData;
public:
// ...constructor
template<typename Type = T> // when T == `std::vector<>`
auto print() const -> typename std::enable_if<is_std_vector<Type>::value>::type
{
for (const auto element : mData)
std::cout << element << "\n";
}
template<typename Type = T> // for types other than `std::vector<>`
auto print() const -> typename std::enable_if<!is_std_vector<Type>::value>::type
{
std::cout << mData << std::endl;
}
};
Run Code Online (Sandbox Code Playgroud)
(见在线直播)
如果我有更多其他数据类型,例如自定义向量类或矩阵,该怎么办?我必须定义很多
is_xx_vector吗?
您可以检查类型是所提供的类型的特化,如下所示。通过这种方式,您可以避免为每种类型提供许多特征。该is_specialization基本上是从这个帖子的启发
#include <type_traits> // std::false_type, std::true_type
#include <vector>
// custom MyVector (An example)
template<typename T> struct MyVector {};
template<typename Test, template<typename...> class ClassType>
struct is_specialization final : std::false_type {};
template<template<typename...> class ClassType, typename... Args>
struct is_specialization<ClassType<Args...>, ClassType> final : std::true_type {};
Run Code Online (Sandbox Code Playgroud)
该print函数可能在c++17 中:
void print() const /* noexcept */
{
if constexpr (is_specialization<T, std::vector>::value)// when T == `std::vector<>`
{
for (const auto element : mData)
std::cout << element << "\n";
}
else if constexpr (is_specialization<T, ::MyVector>::value) // custom `MyVector`
{
std::cout << "MyVector\n";
}
else // for types other than `std::vector<>` and custom `MyVector`
{
std::cout << mData << std::endl;
}
}
Run Code Online (Sandbox Code Playgroud)
(见在线直播)
您需要实现一个使用向量作为模板参数的模板类。这对我有用。
template<typename T>
class A
{
public:
T data;
void print(void) {
std::cout << "Data output" << std::endl;
}
// other functions ...
};
template <typename T>
class A<std::vector<T>>
{
public:
std::vector<T> data;
void print() {
for (auto i : data) {
std::cout << "Vector output" << std::endl;
}
}
};
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1279 次 |
| 最近记录: |