簡體   English   中英

std::is_invocable 的奇怪行為

[英]Bizarre behavior of std::is_invocable

我在以下程序中遇到 std::is_invocable 問題:

#include <iostream>
#include <type_traits>

void g() {}

template<bool B, typename T>
void f(T t) {
    if constexpr (B)
        g(t);
}

int main() {
    std::cerr << std::boolalpha <<
        std::is_invocable_v<decltype(&f<true, int>), int> << std::endl;
}

我原以為程序輸出為假,因為 f<true, int> 無法實例化。 但是,GCC(從 10.0.1 20200224 開始)不會編譯,錯誤消息為

test.cpp: In instantiation of 'void f(T) [with bool B = true; T = int]':
test.cpp:14:51:   required from here
test.cpp:9:10: error: too many arguments to function 'void g()'
    9 |         g(t);
      |         ~^~~
test.cpp:4:6: note: declared here
    4 | void g() {}
      |  

和 Clang(從 11.0.0 開始)甚至打印true

在這種情況下,正確的行為是什么?

問題歸結為: decltype(&f<true, int>)實際上實例化f<true, int>嗎?

如果是,則程序格式錯誤,因為該實例化格式錯誤(不能按要求使用int調用g )。

如果不是,那么invocable_v的正確答案是true - 因為函數體上沒有 SFINAE,並且函數的簽名清楚地允許這種調用。

似乎 gcc 認為是(和硬錯誤),而 clang 認為不是(並產生true )。 我認為clang在這里是正確的。 我們的規則是:

[temp.inst]/10 :

如果以涉及重載解析的方式使用函數模板或成員函數模板特化,則隱式實例化特化聲明 ([temp.over])。

[temp.inst]/11

實現不應隱式實例化函數模板、變量模板、成員模板、非虛擬成員函數、成員類、類模板的靜態數據成員或 constexpr if 語句的子語句 ([stmt. if]),除非需要這樣的實例化。

我們在這里確實涉及重載解析(函數地址),但這只是實例化函數模板的聲明 我認為不需要實例化函數模板的定義f返回void ,而不是auto東西),所以 gcc 在這里太急切地實例化它。

也就是說,當然它不應該產生false

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM