【发布时间】:2018-08-24 04:27:14
【问题描述】:
以下代码不起作用,因为推断的模板参数 F 是 std::tuple,而我希望它是 Foo - 前者接受两个模板参数,后者接受一个。
#include <tuple>
template <typename T>
using Foo = std::tuple<int, T>;
template <template <typename> class F>
void foo(F<std::string> bar) {}
void test() {
foo(Foo<std::string>());
}
有什么方法可以使类型推断与using 语句一起工作,而不是将Foo 变成它自己的类?
#include <tuple>
template <typename T>
class Foo {
std::tuple<int, T> bar;
};
template <template <typename> class F>
void foo(F<std::string> bar) {}
void test() {
foo(Foo<std::string>());
}
更多信息
我正在使用 C++17 的 std::variant 以及对单一类型通用的别名类型,我更愿意使用 using 语句声明这些,而不是为每个类型创建包装类。像这样的:
// Assuming Plus, Minus, etc all exist
template <typename T>
using Operation = std::variant<Plus<T>, Minus<T>, Times<T>>;
构建 Haskell 风格的仿函数
本练习的重点是基于 Haskell 的仿函数类型类松散地构建一个小型仿函数库。我已经定义了这样的“类型类”:
template <template <typename> class F>
class Functor {
public:
template <typename T, typename U>
static F<U> fmap(std::function<U(T)> f, F<T> functor);
};
但我还想添加一些糖,以便您可以创建一个通用映射器,该映射器将一个函数映射到任何函数类型,而无需预先指定函子类型:
template <typename T, typename U>
struct FMap {
FMap(std::function<U(T)> f) : f_(f) {}
template <template <typename> class F>
F<U> operator()(F<T> functor) {
return Functor<F>::fmap(f_, functor);
}
private:
std::function<U(T)> f_;
};
template <typename T, typename U>
FMap<T, U> fmap(std::function<U(T)> f) {
return FMap<T, U>(f);
}
这适用于简单的值包装函子:
template <typename T>
class Value {
public:
Value(T value) : value_(value) {}
const T& value() const {
return value_;
}
private:
T value_;
};
template <>
template <typename T, typename U>
Value<U> Functor<Value>::fmap(std::function<U(T)> f, Value<T> value) {
return Value<U>(f(value.value()));
}
void test() {
std::function<std::string(int)> fn = [](int x) {
return std::to_string(x);
};
auto result = fmap(fn)(Value(42));
// result.value() == "42"
}
现在我正试图让它与使用 std::tuple 或 std::variant 的更复杂的类型一起工作,就像上面的例子一样。
template <>
template <typename T, typename U>
Foo<U> Functor<Foo>::fmap(std::function<U(T)> f, Foo<T> value) {
return Foo<U>(std::get<0>(value), f(std::get<1>(value)));
}
void test() {
std::function<std::string(int)> fn = [](int x) {
return std::to_string(x);
};
// This is the desirable syntax but it doesn't build
// fmap(fn)(Foo<int>(42, 7));
// This builds but it's super ugly
fmap(fn).operator()<Foo>(Foo<int>(42, 7));
}
根据下面 SkepticalEmpiricist 的回复,我认为类型别名可能不是这里的方法,相反我将不得不引入小型包装器类 - 除非有 SFINAE 方法可以实现这一点。
这个库主要是一种好奇心,也是我探索一些更高级模板概念的一种方式——感谢您的帮助!
【问题讨论】:
标签: c++ templates type-alias