gpt4 book ai didi

c++ - 如何有条件地在具有相同签名的两个构造函数之间切换?

转载 作者:行者123 更新时间:2023-11-30 02:33:06 25 4
gpt4 key购买 nike

给定一个带有模板参数的类 typename Tclass Tuple我想提供一个特殊的构造函数,如果 Tuplestd::vector -like 成员函数 reservepush_back .如果Tuple没有这样的成员函数,那么我想提供一个特殊的构造函数,如果 Tuple可从可转换为 T 类型的可变参数构造,即

template<typename T, class Tuple>
class vector
{
template<typename... Elements,
typename = decltype(std::declval<Tuple>().push_back(T())),
typename = decltype(std::declval<Tuple>().reserve(size_type()))>
vector(Elements&&... elements)
{ /* ... */ }

template<typename... Elements, typename = typename = decltype(Tuple{ static_cast<T>(std::declval<Elements>())... })>
vector(Elements&&... elements)
{ /* ... */ }
};

Question 1: Clearly, in the code above the compiler doesn't know that I want to take the first constructor whenever possible. How can I achieve the desired behavior anyway?

Question 2: Assuming that the first constructor doesn't exist, why does the following code lead to the compiler error "cannot convert from initializer list to vector<double, Tuple<double>>":

template<typename T>
class Tuple
{
public:
Tuple() { }
Tuple(std::initializer_list<T>) { }
};

int main()
{
vector<double, Tuple<double>> x = { 1, 2, 3 };
return 0;
}

最佳答案

假设我们有两种类型特征:

template <class T, Tuple> struct satisfies_A;
template <class T, Tuple> struct satisfies_B;

我们想提供一个构造函数来根据满意度调用一个或另一个。我们可以首先为每个案例添加一些额外的标签类型的直接构造函数:

template <class> struct tag{};

template <typename T, class Tuple>
class vector
{
struct A_tag { };
struct B_tag { };
struct na_tag { }; // if you want to support a fallback?

public:
template <class U=T, class UTuple=Tuple, class... Elements,
class = std::enable_if_t<satsfies_A<U,UTuple>::value>>
vector(tag<A_tag>, Elements&&... );

template <class U=T, class UTuple=Tuple, class... Elements,
class = std::enable_if_t<satsfies_B<U,UTuple>::value>>
vector(tag<B_tag>, Elements&&... );
};

那些构造函数根据两种不同的类型特征做任何你想让它们做的事情。现在,我们可以引入如下类型:

using ctor_tag = std::conditional_t<
satisfies_A<T, Tuple>::value,
A_tag,
std::conditional_t<
satisfies_B<T, Tuple>::value,
B_tag,
na_tag>>; // or just void

并酌情转发:

template <class Element, class... Elements,
class = std::enable_if_t<!is_template<tag, std::decay_t<Element>>::value>,
class = std::enable_if_t<std::is_constructible<vector, tag<ctor_tag>, Element&&, Elements&&...>::value>>
vector(Element&& element, Elements&&... elements)
: vector(tag<ctor_tag>{}, std::forward<Element>(element), std::forward<Elements>(elements)...)
{ }

类似的东西。

关于c++ - 如何有条件地在具有相同签名的两个构造函数之间切换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35807253/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com