2016-06-20 10 views
8
std::add_pointerは単項であり、たとえば、が、次のコードは、両方のGCC 7.0.0(20160608)とクラン3.9.0によって受け入れられ

:ながら、連結するテンプレートパラメータパック

template <typename ...Ts> 
struct tc1 { 
    using a = std::add_pointer<Ts...>; 
}; 

しかし次のコードはClangに受け入れられました.GCCによって拒否されました。

template <typename ...Ts> 
struct tc2 { 
    template <typename ...Us> 
    using b = std::add_pointer<Ts...,Us...>; 
}; 

有効なC++ですか?構文的には、コンマはパックが空のときに問題になると思われますが、おそらくそれは他の機会には省略されます。例えば、std::common_typeは、コンパイラのいずれについても問題をゼロ以上の引数を受け入れないし、次のプレゼント:

template <typename ...Ts> 
struct tc3 { 
    template <typename ...Us> 
    using c = std::common_type<Ts...,Us...>; 
}; 
+1

注:clangは 'tc2 :: b <>'のようなインスタンス化を拒否しますが、 'tc2 <> :: b 'を受け入れます。 – Holt

+0

これは意味がありますか?いずれのバリデーショナルな記述の長さを専門とするのでしょうか?私はそれを決定するものは見ませんので、具体的な実装になるかもしれませんが、私は未定義の行動である可能性があります – kirinthos

+3

["プログラムは不正であり、診断は必要ありません:\ [... \]有効なすべての特殊化variadicテンプレートの空のテンプレートパラメータパック "](http://eel.is/c++draft/temp.res#8)が必要です。 –

答えて

1

あなたはGCCとクランのテンプレート引数tc3<1 or more>::a<zero or more>、任意の数のため、このコードを使用することができます。

#include <type_traits> 

struct A { 
    template<typename ...Args> A(Args ... args) {} 
}; 

template <typename T, typename ...Ts> 
struct tc3 { 
    template <typename ...Us> 
    using c = std::add_pointer<T(Ts...,Us...)>; 
}; 

int main() { 
    typedef tc3<A, int, float>::template c<unsigned, double>::type ptr;// A(*)(int,float,unsigned,double) 
    typedef tc3<A>::template c<>::type ptr2;    // A(*)() 
    typedef tc3<bool>::template c<int, int>::type ptr3;  // bool(*)(int,int) 
    typedef std::add_pointer<bool(int, int)>::type ptr4; // bool(*)(int,int) 

    return 0; 
} 

However, while the following code is accepted by Clang, it is rejected by GCC:

この次のコードは、前のみinstantinationedクランに受け入れられますが、エラーが発生した後にされています

template <typename ...Ts> 
struct tc2 { 
    template <typename ...Us> 
    using b = std::add_pointer<Ts...,Us...>; 
}; 

template< class T > 
struct add_pointer; 

それが唯一の内部namespace詳細にまたはいくつかの他に取ることができます一つの引数よりも:

可能な実装:

namespace detail { 
    template< class T, bool is_function_type = false > 
    struct add_pointer { 
     using type = typename std::remove_reference<T>::type*; 
    }; 

    template< class T > 
    struct add_pointer<T, true> { 
     using type = T; 
    }; 

    template< class T, class... Args > 
    struct add_pointer<T(Args...), true> { 
     using type = T(*)(Args...); 
    }; 

    template< class T, class... Args > 
    struct add_pointer<T(Args..., ...), true> { 
     using type = T(*)(Args..., ...); 
    }; 

} // namespace detail 

template< class T > 
struct add_pointer : detail::add_pointer<T, std::is_function<T>::value> {}; 

このは一つだけtamplteの引数を取ることができますこのコードをサポートするために行われます:

typedef std::add_pointer<bool(int, int)>::type ptr4; // bool(*)(int,int)