我对下面尝试使用的一些高级模板技术感到陌生,所以我怀疑我的术语可能不太正确。我有一个Box
基类型和几个继承自Box
的类。我试图根据模板参数构建特定子类的实例。
这是Box<T>
类型。 Convert
函数可以使用返回类型U的函数创建新的Box<U>
。
template<typename T>
class Box : public std::enable_shared_from_this<Box<T>> {
public:
// Box<T> --> Box<U>
template <typename Func>
auto Convert(Func f) -> std::shared_ptr<Box<decltype(f(std::declval<T>()))>>;
virtual void Print() {
std::cout << "box" << std::endl;
}
};
我可以像这样创建一个新的Box<int>
类型:
auto box = std::shared_ptr<Box<int>>(new Box<int>());
要转换为另一种类型,我们返回一个类型为ConvertedBox
的子类(实际上我们这样做是因为我们正在懒惰地应用该函数)。
template<typename T, typename U, typename Func>
class ConvertedBox : public Box<T> {
public:
ConvertedBox(typename std::shared_ptr<Box<U>> box, Func func) :
box_(box), func_(func)
{}
virtual void Print() {
std::cout << "converted box" << std::endl;
}
private:
std::shared_ptr<Box<U>> box_;
Func func_;
};
此处构造子类实例的方法。
// implementation of convert
template <typename T>
template <typename Func>
auto Box<T>::Convert(Func f) -> std::shared_ptr<Box<decltype(f(std::declval<T>()))>>
{
using ReturnType = decltype(f(std::declval<T>()));
auto p = new ConvertedBox<ReturnType, T, Func>(this->shared_from_this(), f);
return std::shared_ptr<Box<ReturnType>>(p);
}
现在,我可以使用以下调用构建新的Box<U>
:
auto converted_float_box = box->Convert([](int v) -> float {
return (float)v;
});
我希望能够做的是根据所应用的函数类型专门化Box<>
基类。例如,如果我像这样转换为Box<std::pair<int, int>>
:
auto converted_pair_box = box->Convert([](int v) -> std::pair<int, int> {
return std::make_pair(v, v);
});
我希望能够在仅Box<std::pair<K, V>>
可用的结果上调用函数(我在这里使用print作为示例。在实践中,专业化很复杂)。
converted_pair_box->PairOnlyPrint();
我试图在Box
上专注std::pair<K,V>
,但没有运气。
template<typename K, typename V>
class PairBox : public Box<std::pair<K, V>> {
public:
void PairOnlyPrint() {
std::cout << "only pair box" << std::endl;
};
};
编译器仍在解析为Box<>
,因此PairOnlyPrint
不可用。有没有办法实现这个目标?
编辑1:正如所指出的,Convert
不是免费功能。
答案 0 :(得分:1)
您的class PairBox
不是专业化,专业化将是:
template<typename K, typename V>
class Box<std::pair<K, V>>: public std::enable_shared_from_this<Box<std::pair<K, V>>> {
public:
// Box<T> --> Box<U>
template <typename Func>
auto Convert(Func f)
-> std::shared_ptr<Box<decltype(f(std::declval<std::pair<K, V>>()))>>;
virtual void Print() { std::cout << "pair box" << std::endl; }
void PairOnlyPrint() { std::cout << "only pair box" << std::endl; };
};