คุณจะจัดการกับเวลาการคอมไพล์ที่ยาวขึ้นเมื่อทำงานกับเทมเพลตได้อย่างไร?


13

ฉันใช้ Visual Studio 2012 และเขามีกรณีที่เราเพิ่มพารามิเตอร์แม่แบบให้กับคลาส "เพียง" เพื่อแนะนำ "จุดตะเข็บ" เพื่อให้ในการทดสอบหน่วยเราสามารถแทนที่ส่วนเหล่านั้นด้วยวัตถุจำลอง

โดยปกติคุณจะแนะนำจุดตะเข็บใน C ++ ได้อย่างไร: การใช้อินเตอร์เฟสและ / หรือการผสมตามเกณฑ์บางอย่างที่มีอินเตอร์เฟสนัยโดยใช้พารามิเตอร์เทมเพลตด้วย? เหตุผลหนึ่งที่ต้องถามเรื่องนี้ก็เพราะเมื่อบางครั้งการรวบรวมไฟล์ C ++ ไฟล์เดียว (ที่มีไฟล์แม่แบบที่อาจรวมถึงแม่แบบอื่น ๆ ) ส่งผลให้ในวัตถุไฟล์ที่ถูกสร้างขึ้นที่ใช้เวลาประมาณ 5-10 วินาทีในเครื่องนักพัฒนา .

VS คอมไพเลอร์ยังไม่รวดเร็วโดยเฉพาะอย่างยิ่งในการรวบรวมเทมเพลตเท่าที่ฉันเข้าใจและเนื่องจากรูปแบบการรวมเทมเพลต (คุณได้รวมคำจำกัดความของเทมเพลตในทุกไฟล์ที่ใช้มันโดยอ้อมและอาจเป็นอินสแตนซ์เทมเพลตนั้นทุกครั้ง สิ่งที่ไม่มีส่วนเกี่ยวข้องกับเทมเพลตนั้น) คุณอาจมีปัญหากับเวลาในการคอมไพล์ (เมื่อทำการคอมไพล์แบบเพิ่มเติม)

คุณมีวิธีจัดการกับเวลารวบรวมแบบเพิ่มขึ้น (และไม่เพียง) เมื่อทำงานกับแม่แบบ (นอกเหนือจากคอมไพเลอร์ที่ดีขึ้น / เร็วขึ้น :-))


1
@RobertHarvey การฉีดพึ่งพาทำโดยใช้พารามิเตอร์แม่แบบ ในรหัสการผลิตที่ฉันยกตัวอย่างเหล่านี้ฉันมีเวลารวบรวมช้า
Ghita

5
คุณใช้ C ++ 11 หรือไม่ ดูen.wikipedia.org/wiki/C%2B%2B11#Extern_template
mike30

2
เนื่องจาก Andrei Alexandrescu มีการเขียนแบบ "Modern C ++ design" โปรแกรมเมอร์ C ++ หลายคนคิดว่าพวกเขาต้องใช้เทมเพลตสำหรับทุกสิ่งและทุกอย่างและให้คอมไพเลอร์จัดการให้มากที่สุด ซึ่งโดยทั่วไปจะนำไปสู่เอฟเฟกต์ที่คุณอธิบาย ก่อนหน้านี้ (และในปัจจุบันยังสำหรับโปรแกรมเมอร์ที่ใช้ภาษาอื่น ๆ ) มันก็โอเคอย่างแน่นอนที่จะไม่ใช้แม่แบบและจัดการสิ่งต่าง ๆ เช่นการพึ่งพาการฉีดด้วยกลไกเวลาทำงานแม้ว่ามันจะต้องใช้รอบ CPU มากขึ้นสำหรับผู้ใช้ ) จริง ๆ แล้วฉันมั่นใจว่าโรเบิร์ตนั้นถูกต้อง 100% และนั่นคือวิธีที่คุณคิด
Doc Brown

1
@Ghita: IMHO โดยใช้การเขียนโปรแกรมเทมเพลตเมตามักจะเป็นรูปแบบของการเพิ่มประสิทธิภาพก่อนวัยอันควร (และบางครั้งก็ overkill) - เท่าที่คุณไม่ได้เขียน libs เช่น STL ที่มีข้อกำหนดที่เทียบเท่า คุณแลกเปลี่ยนประสิทธิภาพเพื่อเพิ่มประสิทธิภาพในการรวบรวมครั้งใหญ่บำรุงรักษาน้อยลงและข้อความแสดงข้อผิดพลาดที่เข้าใจยาก การใช้ "เทมเพลต extern" อาจช่วยคุณได้ในระยะสั้น แต่ถ้าฉันอยู่ในรองเท้าของคุณฉันก็จะคิดถึงการปรับปรุงในระยะยาวเช่นกัน
Doc Brown

4
@DocBrown ในทางกลับกันคุณสามารถพูดได้ว่าการหลีกเลี่ยงเทมเพลตเพื่อปรับปรุงประสิทธิภาพการสร้างคือการปรับให้เหมาะสมก่อนเวลาอันควร เทมเพลตเป็นนามธรรมที่สมบูรณ์แบบสำหรับปัญหามากมาย
mike30

คำตอบ:


9

ถ้าพารามิเตอร์แม่แบบของคุณเท่านั้นที่สามารถสรุปได้แน่นอน (และเล็ก) ชุดของค่าคุณสามารถย้ายนิยามของพวกเขาในแฟ้มแหล่งที่มาและใช้instantiation อย่างชัดเจน

ตัวอย่างเช่นaaa.hคุณเพียงแค่ประกาศฟังก์ชันเทมเพลตfและg:

template <int n>
int f();

template <class T>
void g(int a);

สมมติnพารามิเตอร์แม่แบบเท่านั้นที่สามารถเป็น 1, 3, 6, และTพารามิเตอร์แม่แบบจะไม่สามารถอยู่int, และlongvoid *

จากนั้นคุณกำหนดไว้ในaaa.cppลักษณะนี้:

template <int n>
int f()
{
    ...
}

template <class T>
void g(int a)
{
    ...
}

template int f<1>();
template int f<3>();
template int f<6>();

template void g<int>(int a);
template void g<long>(int a);
template void g<void *>(int a);

ด้วยวิธีนี้คอมไพเลอร์ instantiates aaa.cppแม่แบบสำหรับพารามิเตอร์ที่กำหนดเมื่อรวบรวม เมื่อรวบรวมรหัสลูกค้ามันจะถือว่าคำจำกัดความนั้นมีอยู่ที่ใดที่หนึ่งและตัวเชื่อมโยงจะดูแลสิ่งนั้น

#include "aaa.h"

int main()
{
    f<1>();
    f<3>();
    f<6>();

    g<int>(5);
    g<long>(5);
    g<void *>(5);
}

คุณสามารถสร้างอินสแตนซ์คลาสเทมเพลตได้อย่างชัดเจนเช่นกัน ข้อเสียเปรียบคือคุณไม่สามารถใช้fหรือgกับพารามิเตอร์แม่แบบอื่น ๆ

#include "aaa.h"

int main()
{
    f<5>();
}

ผลลัพธ์ใน

undefined reference to `int f<5>()'

ฉันใช้เทคนิคนี้ในโครงการที่มีคลาสที่ซับซ้อนน้อยขึ้นอยู่กับพารามิเตอร์เทมเพลตจำนวนเต็ม (<10) ชุดและลดเวลาการคอมไพล์ลงอย่างมาก (เนื่องจากคอมไพเลอร์ไม่จำเป็นต้องแยกวิเคราะห์คำจำกัดความเทมเพลตที่ซับซ้อนเมื่อรวบรวมรหัสลูกค้า) . แน่นอนคุณอาจได้รับการปรับปรุงน้อยกว่านี้ขึ้นอยู่กับรหัสจริง


2

เมื่อฉันใช้วิธีแก้ปัญหาที่แปลกประหลาดสำหรับปัญหาที่คล้ายกัน: รวมถึง STL นำไปสู่การรวบรวมเวลาเช่นหลายวินาทีต่อไฟล์ต้นฉบับ - ไม่ว่ามันจะเล็กเพียงใดก็ตาม ดังนั้นฉันจึงรวมไฟล์ต้นฉบับทั้งหมดของฉันไว้ในไฟล์หลักหนึ่งไฟล์และเวลารวบรวมต่อไฟล์แทบจะไม่เปลี่ยนแปลง ... ซึ่งหมายถึงการเพิ่มความเร็วของปัจจัย 20+ เนื่องจากฉันมีเพียงไฟล์เดียวในการรวบรวม

เพื่อให้การออกแบบสะอาดฉันยังคงรักษา makefile แต่ไม่เคยใช้จริง (ยกเว้นการตรวจสอบยังคงใช้งานได้)


0

เราเคยใช้ไฟในภารกิจใหญ่เพื่อสร้างส่วนหัวที่คอมไพล์แล้วและเทมเพลตที่คอมไพล์แล้วค้างคืนและสร้างต่อจากวันถัดไป

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