2015-03-04 12 views
8

Tôi đã viết một số hàm constexpr và sử dụng chúng trong static_asserts để kiểm soát một số giới hạn tài nguyên. Nhưng tôi muốn không chỉ thực thi biến vị ngữ thời gian biên dịch mà còn để xem các giá trị thực được tính toán trong quá trình biên dịch thông thường hoặc ít nhất khi xác nhận không thành công.Làm cách nào để in kết quả tính toán thời gian biên dịch trong C++?

Có nhiều cách để in thông điệp chuỗi trong quá trình biên dịch, nhưng những gì về kết quả in của tính toán constexpr?

+3

Xấu hổ đối số tin nhắn của 'static_assert' không thể thực hiện việc này. –

+2

bạn có thể sử dụng chẩn đoán trình biên dịch thông thường bằng cách buộc một kiểu không đầy đủ về lỗi điều kiện, điều này sẽ dẫn đến các đối số mẫu được hiển thị trong đầu ra trình biên dịch, [như ở đây] (http://coliru.stacked-crooked.com/a/ d2a8871788e97987) –

+0

Tôi có thể làm điều này với VC++ (xem câu trả lời của tôi). Có lẽ ai đó có thể thử xem liệu kỹ thuật tương tự có thể được sử dụng trong gcc – JavaMan

Trả lời

5

Dưới đây là một số mã khai thác thông báo chẩn đoán của gcc để in các giá trị quan tâm sau một thông báo khẳng định. Để tìm các giá trị của sự quan tâm, bạn chỉ cần tìm kiếm trên chuỗi lỗi cho T x =:

#include <string> 

template <class T, T x, class F> 
void transparent(F f) { f(); } 


template <bool B> 
constexpr void my_assert() { 
    static_assert(B, "oh no"); 
} 

template <int X> 
void f() { 
    transparent<int, X+7>([]{ 
     transparent<long, X*X*X>([]{ 
      my_assert<X+10==-89>(); });}); 
} 

int main() { 
// f<3>(); 
    f<4>(); 
// f<-99>(); 
} 

Đây là lỗi mà nó đã cho tôi:

g++ h.cpp -std=c++11 h.cpp: In instantiation of ‘constexpr void my_assert() [with bool B = false]’: h.cpp:16:34: required from ‘f() [with int X = 4]::__lambda0::__lambda1’ h.cpp:15:35: required from ‘struct f() [with int X = 4]::__lambda0::__lambda1’ h.cpp:16:38: required from ‘f() [with int X = 4]::__lambda0’ h.cpp:14:28: required from ‘struct f() [with int X = 4]::__lambda0’ h.cpp:16:41: required from ‘void f() [with int X = 4]’ h.cpp:21:10: required from here h.cpp:9:5: error: static assertion failed: oh no static_assert(B, "oh no"); ^ h.cpp:4:6: error: ‘void transparent(F) [with T = long int; T x = 64l; F = f() [with int X = 4]::__lambda0::__lambda1]’, declared using local type ‘f() [with int X = 4]::__lambda0::__lambda1’, is used but never defined [-fpermissive] void transparent(F f) { f(); } ^ h.cpp:4:6: error: ‘void transparent(F) [with T = int; T x = 11; F = f() [with int X = 4]::__lambda0]’, declared using local type ‘f() [with int X = 4]::__lambda0’, is used but never defined [-fpermissive]

Lưu ý rằng in đậm phần

+0

Điều đó có hiệu quả không, cảm ơn! Bất kỳ ý tưởng làm thế nào để phát ra một thông báo cảnh báo để biên dịch tiếp tục? –

0

Mã VC++ của tôi in, trong quá trình biên dịch, giá trị của nhiều hằng số thời gian biên dịch theo ý muốn của bạn (ví dụ: cấu trúc kích thước) và tiếp tục biên dịch mà không có lỗi:

// cpptest.cpp : Defines the entry point for the console application. 
// 

#include "stdafx.h" 
//#define VALUE_TO_STRING2(x) #x 
//#define VALUE_TO_STRING(x) VALUE_TO_STRING2(x) 


#define TO_STRING(x) #x 
#define FUNC_TEMPLATE_MSG(x,y) "[" x "]""["TO_STRING(y)"]" 

template<unsigned int N,unsigned int M> 
int printN() 
{ 
#pragma message(FUNC_TEMPLATE_MSG(__FUNCSIG__ ,1)) 

    return 0; 
}; 



struct X { 
    char a[20]; 
    int b; 
}; 
struct Y { 
    char a[210]; 
    int b; 
}; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
printN<sizeof(X),__COUNTER__>(); 
printN<sizeof(Y),__COUNTER__>(); 
//..as many compile time constants as you like 
} 

Kết quả mẫu được sản xuất bởi VC++ 2010. Giá trị đích là giá trị tham số mẫu chức năng đầu tiên (0x18 và 0xd8 trong ví dụ) mà VC++ kỳ quặc chọn để xuất dưới dạng giá trị thập lục phân !!

1>------ Build started: Project: cpptest, Configuration: Release Win32 ------ 
1> cpptest.cpp 
1> [int __cdecl printN<0x18,0x0>(void)][1] 
1> [int __cdecl printN<0xd8,0x1>(void)][1] 
1> Generating code 
1> Finished generating code 
1> cpptest.vcxproj -> c:\work\cpptest\Release\cpptest.exe 
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ========== 

Kỹ thuật chính được sử dụng ở đây là trong mỗi lần thực hiện mẫu hàm, chỉ thị #pragma message() được gọi một lần. Macro cụ thể của Microsoft __FUNCSIG__ có thể hiển thị chữ ký của hàm chứa và do đó giá trị số nguyên được sử dụng trong mỗi phiên bản cụ thể của mẫu hàm. Đưa ra tham số COUNTER làm tham số mẫu thứ hai là đảm bảo 2 số nguyên có cùng giá trị vẫn được xem là khác nhau. Số 1 trong chỉ thị #pragma không được sử dụng ở đây nhưng có thể được sử dụng làm số nhận dạng trong trường hợp chúng tôi có nhiều hơn 1 chỉ thị như vậy và cửa sổ đầu ra đầy các thông điệp lộn xộn.

Các vấn đề liên quan