在模板模板参数中抛出多模板 class - 模板绑定?
Throw multiple-template class in a template template parameter - template binding?
鉴于以下 class:
template <class T, template <typename> class B>
class A { B<T> b; };
我现在可以写这样的代码了:
A<float, MyVector> a1;
A<int, MySet> a2;
将多参数 class 放入 B 中的最优雅的方法是什么?像带有 int-keys 的地图?我唯一能想到的是:
template <class U> using C = MyMap<int, U>;
A<float, C<int>> a3;
是否有这样一个模板等同于std::bind,我们可以只提供一部分参数并保留其中一个参数?我很确定该语言没有提供此功能,但人们之前一定已经解决了这个问题。
A<float, MyMap<int, _>> a3;
没有与 std::bind
等效的内置模板,但您可以自己编写一个。这是一个简单的版本,它绑定了您可以扩展以满足您的需要的第一个模板参数:
template <typename T, template <typename...> class B>
struct bind_t1 {
template <typename... Ts>
using type = B<T,Ts...>;
};
那么你只需像这样使用 bind_t1
:
A<float, bind_t1<int, std::map>::type> a3;
请注意,对于您的示例,您需要修改模板参数以采用可变模板模板:
template <class T, template <typename...> class B>
class A { B<T> b; };
这里有一个稍微扩展的版本,它可以在参数列表的开头绑定一些连续的元素:
template <template <typename...> class B, typename... Ts>
struct bind_nt1 {
template <typename... Us>
using type = B<Ts...,Us...>;
};
//Usage
A<std::less<int>, bind_nt1<std::map, int, float>::type> a3;
这是一个基于 std::bind
做事方式的通用版本。它不做任何验证并且可能有一些边缘情况,但它是一个很好的起点。感谢 Piotr Skotnicki 的改进。
template <std::size_t N>
struct placeholder{};
template <template <typename...> class B, typename... Ts>
struct bind_t {
private:
template <typename T, typename UTuple>
struct resolve_placeholder {
using type = T;
};
template <std::size_t N, typename UTuple>
struct resolve_placeholder<placeholder<N>, UTuple> {
using type = typename std::tuple_element<N-1, UTuple>::type;
};
public:
template <typename... Us>
using type = B<typename resolve_placeholder<Ts, std::tuple<Us...>>::type...>;
};
//Usage
A<int, bind_t<std::map, float, placeholder<1>, std::less<float>>::type> a3;
使用这个,你甚至可以改变模板参数的顺序:
//std::map<int,float>
bind_t<std::map, placeholder<2>, placeholder<1>>::type<float, int> b;
鉴于以下 class:
template <class T, template <typename> class B>
class A { B<T> b; };
我现在可以写这样的代码了:
A<float, MyVector> a1;
A<int, MySet> a2;
将多参数 class 放入 B 中的最优雅的方法是什么?像带有 int-keys 的地图?我唯一能想到的是:
template <class U> using C = MyMap<int, U>;
A<float, C<int>> a3;
是否有这样一个模板等同于std::bind,我们可以只提供一部分参数并保留其中一个参数?我很确定该语言没有提供此功能,但人们之前一定已经解决了这个问题。
A<float, MyMap<int, _>> a3;
没有与 std::bind
等效的内置模板,但您可以自己编写一个。这是一个简单的版本,它绑定了您可以扩展以满足您的需要的第一个模板参数:
template <typename T, template <typename...> class B>
struct bind_t1 {
template <typename... Ts>
using type = B<T,Ts...>;
};
那么你只需像这样使用 bind_t1
:
A<float, bind_t1<int, std::map>::type> a3;
请注意,对于您的示例,您需要修改模板参数以采用可变模板模板:
template <class T, template <typename...> class B>
class A { B<T> b; };
这里有一个稍微扩展的版本,它可以在参数列表的开头绑定一些连续的元素:
template <template <typename...> class B, typename... Ts>
struct bind_nt1 {
template <typename... Us>
using type = B<Ts...,Us...>;
};
//Usage
A<std::less<int>, bind_nt1<std::map, int, float>::type> a3;
这是一个基于 std::bind
做事方式的通用版本。它不做任何验证并且可能有一些边缘情况,但它是一个很好的起点。感谢 Piotr Skotnicki 的改进。
template <std::size_t N>
struct placeholder{};
template <template <typename...> class B, typename... Ts>
struct bind_t {
private:
template <typename T, typename UTuple>
struct resolve_placeholder {
using type = T;
};
template <std::size_t N, typename UTuple>
struct resolve_placeholder<placeholder<N>, UTuple> {
using type = typename std::tuple_element<N-1, UTuple>::type;
};
public:
template <typename... Us>
using type = B<typename resolve_placeholder<Ts, std::tuple<Us...>>::type...>;
};
//Usage
A<int, bind_t<std::map, float, placeholder<1>, std::less<float>>::type> a3;
使用这个,你甚至可以改变模板参数的顺序:
//std::map<int,float>
bind_t<std::map, placeholder<2>, placeholder<1>>::type<float, int> b;