Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Templates 如何找到具有默认值的可变数量的constexpr std::数组的constexpr max_Templates_C++14_C++17_Variadic Templates_Template Meta Programming - Fatal编程技术网

Templates 如何找到具有默认值的可变数量的constexpr std::数组的constexpr max

Templates 如何找到具有默认值的可变数量的constexpr std::数组的constexpr max,templates,c++14,c++17,variadic-templates,template-meta-programming,Templates,C++14,C++17,Variadic Templates,Template Meta Programming,因此,对于N的各种值,我有许多constepr std::array。在这种情况下: constexpr std::array<int, 3> r1 {1, 3, 5}; constexpr std::array<int, 2> r2 {3, 4}; constexpr std::array<int, 4> r3 {1, 2, 5, 6}; constexpr std::array<int, 2> r4 {2, 6}; 如图所示: constex

因此,对于
N
的各种值,我有许多
constepr std::array
。在这种情况下:

constexpr std::array<int, 3> r1 {1, 3, 5};
constexpr std::array<int, 2> r2 {3, 4};
constexpr std::array<int, 4> r3 {1, 2, 5, 6};
constexpr std::array<int, 2> r4 {2, 6};
如图所示:

constexpr auto max_entry = dlx::the_max(r1, r2, r3);
std::cout << max_entry << '\n';
但它的最终结果是:

error: no matching function for call to 'the_max2<int>(int, const std::array<int, 3>&, const std::array<int, 2>&, const std::array<int, 4>&)'
错误:调用“the_max2(int,const std::array&,const std::array&,const std::array&)”时没有匹配的函数
只需要1个参数,但收到4个参数,并且:

 error: 'value_type' is not a member of 'const std::array<int, 3>&'
错误:“value\u type”不是“const std::array&”的成员

有人告诉我我做错了什么吗?任何帮助都将不胜感激。

有些问题,没有特别的顺序

(1) 正如S.M.所指出的,您忘记了
typename
之前的
T::value\u type

template<typename B, typename T, typename... Ts> // .......................VVVVVVVV
constexpr std::enable_if_t<std::is_arithmetic_v<B> && std::is_arithmetic_v<typename T::value_type>, std::common_type_t<B, typename T::value_type>>
(3) 当您应该使用
auto
(或者
typename T::value\u type
,如果您愿意,您已经使用了
int
类型作为
v

(4) “公共类型”还应该评估
Ts::value\u类型,因此

// ...........................................VVVVVVVVVVVVVVVVVVVVVVVVVV
std::common_type_t<B, typename T::value_type, typename Ts::value_type...>
(6) 我建议将参数作为常量指针而不是右值接收

 //..........VVVVVVV......VVVVVVV.......VVVVVVV
 the_max2 (B const & b, T const & t, Ts const & ... ts)
下面是一个完整的编译示例(简化为只检测一次返回的公共类型)

如果您可以使用C++17而不是C++14,那么您可以使用模板折叠来恢复
std::is_算术
SFINAE测试,如下所示

template <typename B, typename ... Ts,
          typename RT = std::common_type_t<B, typename Ts::value_type...>>
constexpr RT the_max3 (B const & b, Ts const & ... ts)
 { return std::max<RT>({b, *std::max_element(ts.cbegin(), ts.cend())...}); }
template <typename B, typename ... Ts,
          typename RT = std::common_type_t<B, typename Ts::value_type...>>
constexpr std::enable_if_t<
     (std::is_arithmetic<B>::value && ...
   && std::is_arithmetic<typename Ts::value_type>::value), RT>
   the_max3 (B const & b, Ts const & ... ts)
 { return std::max<RT>({b, *std::max_element(ts.cbegin(), ts.cend())...}); }
模板
constexpr std::启用<
(std::is_算术::value&&。。。
&&std::is_算术::值),RT>
_max3(B常量和B,Ts常量和…Ts)
{返回std::max({b,*std::max_元素(ts.cbegin(),ts.cend())…});}

您需要将
std::is_算术
特性应用于传递参数的
value_type
,而不是将参数本身传递给它们,您还需要从模板参数中删除引用,因为您正在使用转发引用

使用


你好像忘了这里的关键字
typename
std::is\u算术\u v
。不错,但是。。。这个问题被标记为C++14
如果constexpr
只能从C++17获得(模板折叠允许更大的简化)@Sebastian-OK;所以
如果constexpr
可用。是的,很抱歉我没有注意到标签。我把它固定在C++上14@Jans-不,请:阅读OP的评论:他接受C++17并更改了标记。@Sebastian
impl::all
仅用于将包
Preds
扩展为
all\u dummy
的参数,以便您可以使用它检查所有
Preds
是否为真,
all\u dummy!=所有虚拟的
检查一些测试。强制转换
(void)Preds
只是为了避免未使用表达式的警告。请注意,
impl::all
的技巧在c++17中并不是真正需要的,因为你有折叠表达式,你可以像@max66在他的答案中那样使用它。问:有没有理由更喜欢
std::is_算术::value
而不是
std::is_算术
?感谢您提供模板折叠示例。我还没有尝试过模板折叠,这对我来说将是极好的学习材料。(同时,为我犯的愚蠢错误感到抱歉,谢谢你指出它们!Eeep!)@Sebastian-抱歉,
std::is_算术::value
是我的编译器的一个问题:太旧了,不支持
std::is_算术_v
。作为你的第一个额外建议,您认为将返回类型从
RT
更改为:
std::enable_if_t
有什么问题吗?这样,我可以通过检查公共类型来保留is_算法?或者这是荒谬的吗?@Sebastian-是的:我想应该行得通;我现在明白了,这是一个双SFINAE过滤器;第一个在
RT
模板类型本身上,第二个在返回值上;据我记忆所及,我在昨天之前从未做过类似的事情(在C++17折叠案例中),但我不明白为什么不应该这样做。
// ...........................................VVVVVVVVVVVVVVVVVVVVVVVVVV
std::common_type_t<B, typename T::value_type, typename Ts::value_type...>
   using rt = std::common_type_t<B, typename T::value_type, typename Ts::value_type...>;
   // ...
   return std::max<rt>(v, the_max2(b, ts...));
   // ............^^^^
 //..........VVVVVVV......VVVVVVV.......VVVVVVV
 the_max2 (B const & b, T const & t, Ts const & ... ts)
#include <array>
#include <iostream>
#include <algorithm>
#include <type_traits>

template <typename B>
constexpr std::enable_if_t<std::is_arithmetic<B>::value, B>
   the_max2 (B const & b)
 { return b; }


template <typename B, typename T, typename ... Ts,
          typename RT = std::common_type_t<B, typename T::value_type,
                                           typename Ts::value_type...>>
constexpr std::enable_if_t<std::is_arithmetic<B>::value
                        && std::is_arithmetic<typename T::value_type>::value, RT>
   the_max2 (B const & b, T const & t, Ts const & ... ts)
 {
   const auto v = *std::max_element(t.cbegin(), t.cend());
   return std::max<RT>(v, the_max2(b, ts...));
 }

int main()
 {
   constexpr std::array<short, 3> r1 {{1, 3, 5}};
   constexpr std::array<int, 2> r2 {{3, 4}};
   constexpr std::array<long, 4> r3 {{1, 2, 5, 6}};
   constexpr std::array<long long, 2> r4 {{2, 6}};

   auto  m { the_max2(4l, r1, r2, r3, r4) };

   std::cout << m << std::endl;
 }
template <typename B, typename ... Ts,
          typename RT = std::common_type_t<B, typename Ts::value_type...>>
constexpr RT the_max3 (B const & b, Ts const & ... ts)
 { return std::max<RT>({b, *std::max_element(ts.cbegin(), ts.cend())...}); }
template <typename B, typename ... Ts,
          typename RT = std::common_type_t<B, typename Ts::value_type...>>
constexpr std::enable_if_t<
     (std::is_arithmetic<B>::value && ...
   && std::is_arithmetic<typename Ts::value_type>::value), RT>
   the_max3 (B const & b, Ts const & ... ts)
 { return std::max<RT>({b, *std::max_element(ts.cbegin(), ts.cend())...}); }
namespace impl {
    template <bool... Preds> struct all_dummy;
    template <bool... Preds> using all = std::is_same<all_dummy<Preds...>, all_dummy<((void)Preds, true)...>>;
}

template<typename T, typename... Ts>
constexpr std::enable_if_t<
    impl::all<
        std::is_integral<typename std::remove_reference_t<T>::value_type>::value
    >::value,
    typename std::remove_reference_t<T>::value_type
>
the_max2(T&& t) {
    const int v = *std::max_element(t.cbegin(), t.cend());
    return v;
}


template<typename T, typename... Ts, typename R = 
    std::common_type_t<
            typename std::remove_reference_t<T>::value_type,
            typename std::remove_reference_t<Ts>::value_type...>
>
constexpr std::enable_if_t<
    impl::all<
        std::is_integral<typename std::remove_reference_t<T>::value_type>::value,
        std::is_integral<typename std::remove_reference_t<Ts>::value_type>::value...
    >::value,
    R
>
the_max2(T&& t, Ts&&... ts) {
    const int v = *std::max_element(t.cbegin(), t.cend());
    return std::max<R>(v, the_max2(ts...));
}
namespace impl {
    template <bool... Preds> struct all_dummy;
    template <bool... Preds> using all = std::is_same<all_dummy<Preds...>, all_dummy<((void)Preds, true)...>>;
}


template<typename T, typename... Ts, typename R =
    std::common_type_t<
        typename std::remove_reference_t<T>::value_type,
        typename std::remove_reference_t<Ts>::value_type...>
>
constexpr std::enable_if_t<
    impl::all<
        std::is_integral_v<typename std::remove_reference_t<T>::value_type>,
        std::is_integral_v<typename std::remove_reference_t<Ts>::value_type>...
    >::value,
    R
>
the_max2(T&& t, Ts&&... ts) {
    const int v = *std::max_element(t.cbegin(), t.cend());
    if constexpr (sizeof...(ts) > 0) {
        return std::max<R>(v, the_max2(ts...));
    } else {
        return v;
    }
}