[英]Default template type based on later template type
I have a function which creates an object and inserts it into a container.我有一个 function ,它创建一个 object 并将其插入容器中。 In most cases, the object type is the same as that of the container elements.
在大多数情况下,object 类型与容器元素的类型相同。 Then, I don't want to have to specify the object type.
然后,我不想指定 object 类型。 But for containers holding
std::variant
, I want to be able to specify the object type as the first template parameter.但是对于持有
std::variant
的容器,我希望能够将 object 类型指定为第一个模板参数。 Here's the non-working example:这是非工作示例:
template<typename T>
using remove_qualifiers = std::remove_cv_t<std::remove_reference_t<T>>;
template<typename T>
using IteratorType = decltype( std::declval<remove_qualifiers<T>>().end() );
template<typename T>
using ElementType = decltype( *( std::declval<remove_qualifiers<T>>().end() ) );
template<typename E = ElementType<T>, typename T, typename ... Args>
IteratorType<T> insert( T& someContainer, Args&& ... ){
IteratorType<T> it { someFindFunc() };
return someContainer.insert(it, E{std::forward<Args>(args) ...});
}
The problem is, that the default type for E
is based on T
, which at this point is not declared yet.问题是,
E
的默认类型基于T
,此时尚未声明。 But if I change the order, then calling the function becomes awkward.但是如果我更改顺序,那么调用 function 就会变得很尴尬。
How can I make this pattern work, so that I can call the function both with and without specifying E
?如何使这种模式起作用,以便我可以在指定和不指定
E
的情况下调用 function ?
I guess this is likely a case of not finding the right search terms.我想这可能是没有找到正确的搜索词的情况。 I looked at this , this , this , and this one, and they don't appear to be what I'm looking for.
我看了这个、 这个、 这个和这个,它们似乎不是我要找的。
Consider wrap it into a class template so that you don't need to worry about specifying the type of the container.考虑将其包装到 class 模板中,这样您就不必担心指定容器的类型。
template <typename T>
class Inserter {
public:
Inserter(T& someContainer): container{someContainer} {}
using IteratorType = decltype( std::declval<remove_qualifiers<T>>().end() );
template <typename E = ElementType<T>, typename... Args>
IteratorType insert(Args&&... args) {
IteratorType it = container.begin(); // just for sample
return container.insert(it, E{std::forward<Args>(args) ...});
}
private:
T& container;
};
Then,然后,
std::vector<std::variant<int, double>> v;
Inserter{v}.insert<int>(1);
Inserter{v}.insert<double>(1.1);
If you are not using some sort of emplace, you should just move construction to the caller.如果您不使用某种 emplace,则应该将构造移至调用者。 For simplicity I'm using
push_back
instead of insert
.为简单起见,我使用
push_back
而不是insert
。
template <typename T, typename Value>
inline auto insert(T& container, Value&& value) {
container.push_back(std::forward<Value>(value));
}
But let's assume you are really constructing the type in place.但是让我们假设您确实在适当地构造类型。
template <typename T, typename... Args>
inline auto emplace(T& container, Args&&... args) {
container.emplace_back(std::forward<Args>(args)...);
}
This is possibly all you need.这可能就是您所需要的。 You can construct any type, variants as well.
您也可以构造任何类型、变体。
struct A { int n; };
struct B { int n; };
auto a = std::vector<A>{};
emplace(a, 100);
auto b = std::vector<B>{};
emplace(b, 100);
auto ab = std::vector<std::variant<A, B>>{};
emplace(ab, std::in_place_type_t<A>{}, 100); // tell the type
emplace(ab, 100); // ambigious, compile error
As for your specific use-case, there is no way of deducing some sort of default type of a variant.至于您的特定用例,无法推断出某种默认类型的变体。 You always have to tell explicitly what to construct.
你总是必须明确地告诉你要构造什么。
You can reinvent the wheel, create an overload for variants and then hide std::in_place_type_t
.您可以重新发明轮子,为变体创建重载,然后隐藏
std::in_place_type_t
。 But generally this problem has been solved by the STL for any type that can be constructed in place.但通常这个问题已经被 STL 解决了,对于任何可以就地构建的类型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.