4

std::enable_ifを関数引数とテンプレート引数の間に使用する違いは何ですか?関数の引数とテンプレートの引数としてstd :: enable_ifを使用する違いは何ですか?

I持って次の2つの関数テンプレート:(https://godbolt.org/g/ON4Ryaからのように)次のアセンブリを製造

#include <type_traits> 

template<typename T> 
void f_function(T, typename std::enable_if_t<std::is_pod<T>::value, int> = 0) 
{ 
} 

template<typename T, typename = typename std::enable_if_t<std::is_pod<T>::value>> 
void f_template(T) 
{ 
} 

int main() 
{ 
    int x = 1; 
    f_function(x); 
    f_template(x); 
} 

main: 
     pushq %rbp 
     movq %rsp, %rbp 
     subq $16, %rsp 
     movl $1, -4(%rbp) 
     movl -4(%rbp), %eax 
     movl $0, %esi 
     movl %eax, %edi 
     call void f_function<int>(int, std::enable_if<std::is_pod<int>::value, int>::type) 
     movl -4(%rbp), %eax 
     movl %eax, %edi 
     call void f_template<int, void>(int) 
     movl $0, %eax 
     leave 
     ret 
void f_function<int>(int, std::enable_if<std::is_pod<int>::value, int>::type): 
     pushq %rbp 
     movq %rsp, %rbp 
     movl %edi, -4(%rbp) 
     movl %esi, -8(%rbp) 
     nop 
     popq %rbp 
     ret 
void f_template<int, void>(int): 
     pushq %rbp 
     movq %rsp, %rbp 
     movl %edi, -4(%rbp) 
     nop 
     popq %rbp 
     ret 

f_function 2つの関数のパラメータとf_templateを有するということで明らかな違いに加え2つのテンプレート引数を持ち、それらの違いは何ですか?互いに重複して使用されていますか?

+1

戻り値の型に追加することもできます。あなたの最初のバージョン(f_function)に必要なスタックとは別に、これらは全く同じように動作します。 – lorro

答えて

3

簡単な例として、あなたがこれを行うことができますが:

int main() { 
    // f_function(std::string{}); // (1) 
    // f_template<std::string>(std::string{}); // (2) 
    f_template<std::string, void>(std::string{}); 
} 

(1)(2)は明白な理由のためにコンパイルされませんが(std::stringが受け入れタイプではない)、f_templateすることができますTがポッドタイプでなくても、トリックで使用してください。


有効な代替は、次のようになります。

template<typename T, std::enable_if_t<std::is_pod<T>::value>* = nullptr> 
void f_template(T) 
{ } 

は、もう一つは次のようになります。

template<typename T> 
std::enable_if_t<std::is_pod<T>::value> 
f_template(T) 
{ } 

代わりにガードとしてパラメータパックを必要とするより多くの無名の1:

template<typename T, typename..., typename = typename std::enable_if_t<std::is_pod<T>::value>> 
void f_template(T) 
{ } 

これらはすべて機能しますあなたがそれらを回避することはできません(少なくとも、私はそれを行う方法はわかりませんが、多分誰かが良いトリックで来るでしょう)。

+0

パックが空であることを確認するために、より曖昧なものが欠けています:-)。 – Jarod42

+0

@ Jarod42コンパイル時にエラーが発生するのは当然ですが、もっともらしくないタイプのシーケンスを使ってブレークしようとする開発者の顔を見る価値があります!! ;-) – skypjack

+0

@ Jarod42追加と言及。ありがとうございました。 – skypjack

関連する問題