2012-01-06 35 views
4

當我嘗試編譯爲什麼術語不評估一個帶有0個參數的函數?

template<bool val> 
struct boolean { static const bool value = val; }; 

template<typename T> 
struct is_callable : boolean<sizeof((*(T*)0)()) >= 0> { };   // error! 

int main(void) { bool b = is_callable<int (*)()>::value; } 

我得到:

error C2064: term does not evaluate to a function taking 0 arguments 
    see reference to class template instantiation 'is_callable<T>' being compiled 

我敢肯定int (*)()是可調用與0參數...那麼,爲什麼不這樣編?

+2

工程在GCC 4.6.2。 – 2012-01-06 02:19:39

+0

@KerrekSB:呵呵,這很有趣...我用VC 2010試了一下,它也給出了一個錯誤。那麼它是一個錯誤?我不知道,因爲有一個空指針被解除引用,但實際上我沒有看到它的任何錯誤... – Mehrdad 2012-01-06 02:22:48

+5

沒有取消引用。 'sizeof'不會評估它的參數。 – 2012-01-06 02:24:30

回答

0

問題不在於使用int()。您可以從示例中完全刪除並獲得相同的錯誤。問題是當用作非類型模板參數時,sizeof表達式本身。實施例

template<bool val> 
struct boolean { }; 

template<typename T> 
struct is_callable : boolean<sizeof((*(T*)0)()) >= 0> // Error 
{ 
    void Test() 
    { 
    auto x = sizeof((*(T*)0)()) >= 0; // Compiles 
    } 

}; 

希望另一C++的人可以沿着來,並確定是否這sizeof表達是作爲一種類型的參數簡單地非法或者如果這是剛剛在MS C++編譯器的限制。

+3

這裏沒有「type」參數。 'val'是一個*非類型*參數。 – 2012-01-06 02:25:35

+0

@KerrekSB doh。更正說「模板參數」。 – JaredPar 2012-01-06 02:26:32

+0

它仍然是*非類型*模板參數。 – 2012-01-06 02:27:04

0

對我來說這個工程。

typedef int (*X)(); 

    template<typename T> 
    struct is_callable : boolean<sizeof((*(X*)(T*)0)()) >= 0> { };   // works! 

因此,看起來編譯器並不確定在實例化模板類時,您總是會傳遞一個指向T的函數指針!所以,強制編譯器進行明確的轉換。

[編輯]:另外,在進一步思考時,我不明白你真的想要做什麼。你想測量一個函數指針的大小,它只需要一個參數?對於具有不同返回類型的函數,這將如何變化?爲什麼你需要模板來獲得一個常量表達式(sizeof(void *))?

請檢查該線程更多的理解 What is guaranteed about the size of a function pointer?

0

你可以只使用簡單的模板專業化。

#include <stdio.h> 

template<typename T> 
struct func_with_zero_args { static const bool value = false; }; 
template<> 
struct func_with_zero_args <int (*)()> { static const bool value = true; }; 

#define STRINGIFY(t) "" #t 
#define TEST(t) printf(STRINGIFY(t) ": %s\n", (func_with_zero_args<t>::value ? "yes" : "no")); 

int 
main(int argc, const char* argv[]) 
{ 
    TEST(void); 
    TEST(void (*)(void)); 
    TEST(void (*)(int)); 
    TEST(int (*)(void)); 
    TEST(int (*)(int)); 
    return 0; 
} 

生成(採用克++(Ubuntu的/ Linaro的4.7.3-1ubuntu1)4.7.3)

 
void: no 
void (*)(void): no 
void (*)(int): no 
int (*)(void): yes 
int (*)(int): no 
相關問題