ผ่านแนวคิดไปยังฟังก์ชั่น


12

เนื่องจากแนวคิดถูกกำหนดให้เป็นเพรดิเคตเวลาคอมไพล์จึงเป็นไปได้หรือไม่ที่จะใช้เพรดิเคตเหล่านี้ซ้ำสำหรับอัลกอริธึมเวลารวบรวม เช่นเป็นไปได้ไหมที่จะตรวจสอบว่าทุกประเภทใน tuple สอดคล้องกับแนวคิดหรือไม่? เท่าที่ฉันได้เห็นมันเป็นไปไม่ได้ที่จะส่งแนวคิดไปยังฟังก์ชั่นในทางใดทางหนึ่งซึ่งทำให้ฉันกลับไปใช้แม่แบบสำหรับกรณีเหล่านี้

#include <type_traits>

template<typename T>
concept FloatLike = std::is_same_v<T, float>;

struct IsFloat
{
    template<typename U>
    constexpr static bool test()
    {
       return FloatLike<U>;
    }
};


template<typename Predicate, typename... T>
constexpr bool all_types()
{
    return (Predicate::template test<T>() && ...);
}


int main()
{
   static_assert(all_types<IsFloat, float, float>());
   static_assert(!all_types<IsFloat, float, int>());
}

สิ่งที่ฉันต้องการจะทำคืออะไรเช่นนี้ดังนั้นฉันจึงไม่จำเป็นต้องห่อหุ้มแนวคิดตลอดเวลาเพื่อให้สามารถใช้งานได้:

template<concept Predicate, typename... T>
constexpr bool all_types()
{
    return (Predicate<T> && ...);
}


int main()
{
   static_assert(all_types<FloatLike, float, float>());
   static_assert(!all_types<FloatLike, float, int>());
}

มีวิธีใดที่จะเข้าใกล้สิ่งนี้มากขึ้น?


และจากนั้นจะมีข้อเสนอที่จะเพิ่มแนวคิดของแนวคิด ... BTW, all_types()ได้ง่ายอย่างมีนัยสำคัญโดยใช้นิพจน์พับ... &&:return (... && Predicate::template test<Ts>());
EVG

@Evg มันจะยอดเยี่ยม :)
Igor R.

คำตอบ:


5

มีวิธีใดที่จะเข้าใกล้สิ่งนี้มากขึ้น?

อืมไม่ไม่จริง ไม่อยู่ใน C ++ 20 ไม่มีความคิดในภาษาของเทมเพลตแนวคิด - พารามิเตอร์ในวันนี้ แม้แต่เทมเพลตตัวแปรไม่สามารถใช้เป็นพารามิเตอร์เทมเพลตได้ ดังนั้นหากมีแนวคิดที่จะเริ่มต้นด้วยเราไม่สามารถหลีกเลี่ยงการห่อ

แต่สิ่งที่เราทำได้คือเขียน wrappers ที่ง่ายกว่า หากเราเห็นด้วยที่จะใช้ลักษณะ "แบบเก่า" เป็นเพรดิเคตโดยเฉพาะที่มีลักษณะเหมือนstd::integral_constantของ s เราจะมีคำจำกัดความของแนวคิด "แนวคิด" ที่สั้น ๆ ที่สามารถใช้เป็นเพรดิเคตได้

template<typename T>
using FloatLike = std::is_same<T, float>;

template<template <typename> class Predicate, typename... T>
constexpr bool all_types()
{
    return (Predicate<T>{} && ...);
}

มันดีเท่าที่จะทำได้เท่าที่ฉันเห็น


มันจะทำงานโดยการพิมพ์แลมบ์ดาทั่วไปเป็นเทมเพลตแม่แบบในทางใดทางหนึ่งหรือไม่? ดูเหมือนว่าแลมบ์ดาจะไม่เคยเป็นเทมเพลต แต่ถูกต้องมีเพียงผู้ให้บริการโทรศัพท์เท่านั้น?
Andreas Loanjoe

@AndreasLoanjoe - แน่นอน แลมบ์ดาไม่เคยเป็นแม่แบบ แต่ถ้าคุณเต็มใจส่งลูกแกะไปรอบ ๆ C ++ 20 จะอนุญาตให้คุณทำ ฉันสามารถเพิ่มชุดตัวเลือกได้ภายในไม่กี่นาที
StoryTeller - Unslander Monica

@AndreasLoanjoe - ในความคิดที่สองแลมบ์ดายังคงออกมาอย่างละเอียดมาก ฉันไม่คิดว่ามันเป็นทางเลือกที่ดี นี่ไงล่ะgodbolt.org/z/QSHy8X
StoryTeller - Unslander Monica

ฉันหวังว่าพวกเขาจะเพิ่มสิ่งที่ดีกว่า :) แต่ใช่ดูเหมือนว่านี่คือคำตอบเฉพาะลักษณะประเภทของสไตล์ที่เสนอแนวคิดการทำงานนี้เท่านั้น
Andreas Loanjoe

0

หากเป้าหมายของคุณคือ"ตรวจสอบว่าประเภททั้งหมดใน tuple สอดคล้องกับแนวคิด"หรือไม่คุณสามารถทำสิ่งนี้ได้:

// concept to check if all types in Ts are the same as T
template<typename T, typename... Ts>
concept AllSame = (std::is_same_v<T,Ts> && ...);

// function only accepts floats as template parameters
template<AllSame<float>... Floats>
constexpr void float_foo()
{
}

// function only accepts ints as template parameters
template<AllSame<int>... Ints>
constexpr void int_foo()
{
}

// function only accepts T as template parameters
template<typename T, AllSame<T>... Ts>
constexpr void foo()
{
}

int main()
{
    int_foo<int, int, int>();
    // int_foo<int, int, double>(); // fails to compile
    float_foo<float, float, float>();
    // float_foo<float, float, int>(); // fails to compile
    foo<int, int, int, int>();
    // foo<int, int, int, float>(); // fails to compile
    foo<double, double, double, double>();
    // foo<double, double, double, int>(); // fails to compile

}

สาธิตสด


ทำไมคุณถึงเป็นคนAllSameแปรปรวน แต่ละเทมเพลตพารามิเตอร์ในแพ็คที่นำเสนอโดยข้อ จำกัด ประเภทนั้นมีข้อ จำกัด แยกกันอยู่แล้ว
Davis Herring

@DavisHerring ฉันไม่เข้าใจ คุณหมายถึงแนวคิดหรือพารามิเตอร์เทมเพลท*_foo()ใช่หรือไม่
kanstar

ผมหมายถึงว่ารหัสที่คุณมีผลงานถ้าคุณลบ...บนTsและ&& ...ที่จะใช้มัน (เห็นได้ชัดว่าชื่อAllSameนั้นจะไม่เหมาะสม แต่ฉันไม่แน่ใจว่าทำไมฉันต้องการแสดงนับเป็น unary เช่น<int,int,int>กัน.)
Davis Herring

@DavisHerring แล้วแนวคิดจะไม่เป็นAllSameแต่SameAs(ดูen.cppreference.com/w/cpp/concepts/same_as ) และ OP ต้องการที่จะมีแนวคิดซึ่งจะมีจำนวนของพารามิเตอร์ variadic แม่แบบ
kanstar

std::same_asเห็นได้ชัดว่ามันจะเป็น ฉันไม่คิดว่าส่วนแปรปรวนเป็นประเด็น: มันเป็นเอกลักษณ์ของตัวแปร (ที่ต้องการ) ของแนวคิด และประเด็นของฉันก็คือแง่มุมแปรปรวนของตัวอย่างแนวคิดของคุณนั้นไม่เกี่ยวข้องกับการใช้งาน (เนื่องจากแนวคิดที่ไม่แปรปรวนทำงานร่วมกับชุดพารามิเตอร์เทมเพลตแล้ว)
Davis Herring
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.