7

一意のテンプレート関数を区別するために使用される署名と、一意の関数(テンプレート関数からインスタンス化されたものを含む)を区別するために使用される署名の間に非対称性があることに気付きました。

特に、リターンタイプのみが異なるテンプレート関数は一意であると見なされ、リターンタイプのみが異なるテンプレート関数は冗長であると見なされます。

したがって、インスタンス化の時点で、戻り値のタイプのみが異なる関数テンプレート間で曖昧さを解消する方法について、対応する質問があります。

#include <iostream>

template<typename T>
long foo(T)
{
    std::cout << "long" << std::endl;
    return 0;
}

template<typename T>
char foo(T)
{
    std::cout << "char" << std::endl;
    return '\0';
}

int main()
{
    double d = 0.0;
    long n = foo(d); // <- Ambiguous: How to specify the template function to use?
}

上記のコードでは、テンプレート関数のインスタンス化は、foo先ほど述べた非対称性のためにあいまいです。2つのテンプレート関数定義の存在は有効ですが、戻り型が同じコード行で指定されている場合でも、インスタンス化は無効です。

私は純粋に理論的な学習目的でこの質問をしています。おそらく、このコード構成は、実際には、不十分な設計の兆候である可能性があります。おそらく、それは現実の世界では決して起こらないでしょう。また、テンプレート定義を変更する(または他の変更を行う)ことで、この問題を克服するさまざまな方法を想像することができます。

ただし、それでも、テンプレート定義を変更せずに、インスタンス化の時点でこれら2つのテンプレート関数のあいまいさを解消できるかどうかを知りたいと思います。

4

2 に答える 2

8

テンプレートを使用する場合、実際には2つの異なるオーバーロードを明確にすることができます。それはきれいではありませんが、機能します:

long n = static_cast<long(*)(double)>(&foo)(d);
于 2012-12-03T13:36:31.130 に答える
2

同じ名前、同じパラメーターリスト、異なる戻り型を持つ2つの関数テンプレートが本当に必要な場合は、戻り型をテンプレートパラメーターにすることで、2つを区別するしかありません。

template <typename R, typename T>
R foo(T);

IIRCには、C ++ 11に部分的な関数テンプレートの特殊化がありますが、標準ではそれについて何も見つかりませんでした。ある場合、これは機能するはずです。

//partial function template specializations: C++11 only!
template <typename T>
long foo<long, T>(T)
{
    std::cout << "long" << std::endl;
    return 0;
}

template<typename T>
char foo<char, T>(T)
{
    std::cout << "char" << std::endl;
    return '\0';
}

または、C ++ 03の場合:

template <typename R, typename T>
struct FooImpl;

template <typename T>
struct FooImpl<long, T>
{
  static long doIt(T) 
  {
    std::cout << "long" << std::endl;
    return 0;
  }
};

template <typename T>
struct FooImpl<char, T>
{
  static char doIt(T) 
  {
    std::cout << "char" << std::endl;
    return '\0';
  }
};

template <typename R, typename T>
R foo(T t)
{
  return FooImpl<R, T>::doIt(t);
}

どちらの場合も、メインは次のようになります。

int main()
{
    double d = 0.0;
    long n = foo<long>(d); // specify the return type only
    auto c = foo<char>(n);
}
于 2012-12-03T13:59:31.277 に答える