1

Anthony Williamsからの次のコード スニペットが与えられます。非常に基本的なタプルの例で、ここにあるものはすべて期待どおりに機能します。

#include <iostream>

template<typename ... Types>
class simple_tuple;

template<>
class simple_tuple<>
{};

template<typename First,typename ... Rest>
class simple_tuple<First,Rest...>:
        private simple_tuple<Rest...>
{
        First member;
public:
        simple_tuple(First const& f,Rest const& ... rest):
          simple_tuple<Rest...>(rest...),
                  member(f)
          {}
          First const& head() const
          {
                  return member;
          }
          simple_tuple<Rest...> const& rest() const
          {
                  return *this;
          }
};

template<unsigned index,typename ... Types>
struct simple_tuple_entry;

template<typename First,typename ... Types>
struct simple_tuple_entry<0,First,Types...>
{
        typedef First const& type;
        static type value(simple_tuple<First,Types...> const& tuple)
        {
                return tuple.head();
        }
};

template<unsigned index,typename First,typename ... Types>
struct simple_tuple_entry<index,First,Types...>
{
        typedef typename simple_tuple_entry<index-1,Types...>::type type;
        static type value(simple_tuple<First,Types...> const& tuple)
        {
                return simple_tuple_entry<index-1,Types...>::value(tuple.rest());
        }
};
template<unsigned index,typename ... Types>
typename simple_tuple_entry<index,Types...>::type
        get_tuple_entry(simple_tuple<Types...> const& tuple)
{
        std::cout << "SizeofArgs == " << sizeof...(Types) << std::endl;
        return simple_tuple_entry<index,Types...>::value(tuple);
}

int main()
{
        simple_tuple<int,char,double> st(42,'a',3.141);
        std::cout<<get_tuple_entry<0>(st)<<","
                <<get_tuple_entry<1>(st)<<","
                <<get_tuple_entry<2>(st)<<std::endl;
}

でも気になるのはそのget_tuple_entry機能。
可変引数のテンプレートパラメータの数は呼び出しごとに変わると思っていましたが、sizeof は常に 3 を返します。
そのため、関数は次の (疑似コード) と何とか同等です。

template<unsigned index, <int,char,double> >
typename simple_tuple_entry<index, <int,char,double> >::type
        get_tuple_entry(simple_tuple<int,char,double> const& tuple)
{
        std::cout << "SizeofArgs == " << sizeof...(<int,char,double>) << std::endl;
        return simple_tuple_entry<index,<int,char,double> >::value(tuple);
}

しかし、これはget_tuple_entry戻り値によってのみオーバーロードされることを意味しますが、これは不可能です。呼び出しごとに署名が異なるのはなぜですか?

4

1 に答える 1

5

しかし、これは get_tuple_entry が戻り値によってのみオーバーロードされることを意味しますが、これは不可能です。

get_tuple_entryは関数ではなく、関数テンプレートです。戻り値の型のみが異なる同じ関数の 3 つのオーバーロードと呼ばれるものは同じではありません。これらは、関数テンプレートの個別のインスタンス化です。

get_tuple_entry<0, int, char, double>
get_tuple_entry<1, int, char, double>
get_tuple_entry<2, int, char, double>

これは同じ機能ではありません。

呼び出しごとに可変長のテンプレート パラメーターの数が変わると思っていましたが、sizeof は常に 3 を返します。

もちろん。その関数テンプレートのインスタンス化を呼び出すたびに、 type の同じ引数を渡すsimple_tuple<int,char,double>ため、テンプレート パラメーター パックのサイズが 3 であると推測されるint, char, doubleたびに。呼び出しの違いは、異なるインスタンス化を呼び出すことでget_tuple_entry<0>あり、と同じでget_tuple_entry<1>、異なるインスタンス化ごとにタプルの異なる要素が返されます。

これは本当に

#include <iostream>

template<int N>
void func()
{
    std::cout << N << '\n';
}

int main()
{
    func<0>();
    func<1>();
    func<2>();
}

func<0>()これは、異なるものを出力する 3 つの異なる関数を呼び出しますが、とfunc<1>()func<2>()はすべて異なる関数であるため、同一の署名で問題はありません。マングルされた名前を見ると、異なる署名があることがわかります。たとえば、G++ では_Z4funcILi0EEvv_Z4funcILi1EEvv_Z4funcILi2EEvvが同じ署名ではありません。

于 2012-08-14T13:50:48.747 に答える