関数テンプレートの宣言部分で定義すると、任意の型プロパティでの関数のオーバーロードが失敗します

tmaric

私はこここのトピックに関する素晴らしい記事を見つけました、そして10ページで、著者は2つの重要なことに注意します:

  1. イネーブラーを使用して関数テンプレートがオーバーロードされると、イネーブラーは宣言部分に配置されます。
  2. 通常のディスパッチャを実装する必要はありません。実装にディスパッチする別個のインターフェイス関数です。

ポイント1は、SOでこのソリューションとして見つけることができます著者は(印刷された記事の10ページ)、イネーブラーを関数の引数として使用することも可能であると述べています。これは私がやろうとしたことですが、その例ではADLが失敗しました。

ポイント2は、SFINAEに依存し、関数テンプレートセットを減らしています。イネーブラーが失敗した場合、SFINAEはエラーを報告せず、パラメーターの推定により、最適なテンプレートが選択されます。

そうは言っても、前のを変更しました

#include <type_traits>
#include <iostream>

template<typename Type>
struct tag {}; 

struct Atag {}; 
struct Btag {};

template<typename Type, typename Tag>
struct tag_enabled
{
    static const bool value = std::is_same
    <
        typename tag<Type>::type, 
        Tag 
    >::value;

    typedef typename std::enable_if
    <
        std::is_same
        <
            typename tag<Type>::type, 
            Tag 
        >::value,
        Type
    >::type type; 
};

template<typename A, typename B>
typename std::enable_if
<
    tag_enabled<A, Atag>::value && 
    tag_enabled<B, Btag>::value, 
    A
>::type
worker(
    B const & b
)
{
    A result; 

    std::cout << "Btag -> Atag" << std::endl;

    return result; 
}

template<typename A, typename B>
typename std::enable_if
<
    tag_enabled<A, Atag>::value && 
    tag_enabled<B, Atag>::value, 
    A
>::type
worker(
   B const & b 
)
{
    A result; 

    std::cout << "Atag -> Atag" << std::endl;

    return result; 
}

struct test_a {}; 
struct test_b {}; 

template<>
struct tag<test_a>
{
    typedef Atag type; 
};

template<>
struct tag<test_b>
{
    typedef Btag type;
};

int main()
{
    test_a ta1; 
    test_b tb1; 

    auto ta2 = worker<test_a>(ta1); 
    auto ta3 = worker<test_a>(tb1);

    return 0;
}

私はこれが記事で説明されているように機能することを期待していました:

イネーブラーは、AがAtagでタグ付けされ、BがAtagまたはBtagでタグ付けされているかどうかを確認しようとします。イネーブラー、他の関数テンプレートで有効な場合、一方の関数テンプレートで有効な戻り値の型を生成できません

   tag_enabled<A, Atag>::value && // Check if A is tagged with Atag
   tag_enabled<B, Btag>::value, // Check if B is tagged with Btag
   A

1つの構成に対して有効な戻り値の型を生成できなくても、エラーにはなりません:SFINAE。次に、コンパイラは別のテンプレートを試行し、BがBtagでタグ付けされている場合function<test_a>(tb1)、のように、有効な関数をインスタンス化して使用します。

ただし、機能していないようで、次のようなエラーが発生します。

test-template.cpp: In instantiation of ‘struct tag_enabled<test_a, Btag>’:
test-template.cpp:33:33:   required by substitution of ‘template<class A, class B> typename std::enable_if<(tag_enabled<A, Atag>::value && tag_enabled<B, Btag>::value), A>::type worker(const B&) [with A = test_a; B = test_a]’
test-template.cpp:86:34:   required from here
test-template.cpp:27:13: error: no type named ‘type’ in ‘struct std::enable_if<false, test_a>’
     >::type type; 
             ^
test-template.cpp: In instantiation of ‘struct tag_enabled<test_b, Atag>’:
test-template.cpp:51:33:   required by substitution of ‘template<class A, class B> typename std::enable_if<(tag_enabled<A, Atag>::value && tag_enabled<B, Atag>::value), A>::type worker(const B&) [with A = test_a; B = test_b]’
test-template.cpp:87:34:   required from here
test-template.cpp:27:13: error: no type named ‘type’ in ‘struct std::enable_if<false, test_b>’

イネーブラーを使用することの全体的なポイントがSFINAEに依存することであるとしても、両方の関数テンプレートが有効な選択肢として残っているように思われますか?つまりはそうだ:

typename std::enable_if<(tag_enabled<A, Atag>::value && tag_enabled<B, Atag>::value), A>::type worker(const B&) [with A = test_a; B = test_b]

私はそれtag_enabled<test_b, Atag>::valueが間違っていることを知っています、それは私が期待していることです、enable_ifそしてそれからtypedefがtype定義されていませんこれが、イネーブラーを使用して無効な戻り型を生成し、関数セットを減らすという原則全体のポイントです。

これは実際に著者がadvance記事に対して行っていることです。この例の唯一の違いは、関数テンプレートが2つのパラメーターを取り、両方が何らかの方法でタグ付けされているかどうかがチェックされていることです。Oo私は再び明白な何かを逃しましたか?

jrok

SFINAEは、テンプレート引数の置換中に機能します(関数テンプレートのタイプまたはクラステンプレートの特殊化のいずれかを推測する場合)。

一方、クラス定義内にロジックを配置しました手遅れです。テンプレートがインスタンス化され、引数の型がすでに推定されている場合にのみチェックされ、ハードエラーがトリガーされます。

ただ、取り除くtypedefの内部tag_enabledあなたはそれを必要とせず、あなたはvalue渡すメンバーだけを必要としますenable_if(それは置換の失敗が起こるはずです-enable_if最初のパラメーターの値に基づいてネストされたtypedefを持っているか持っていないでしょう)。

その後、それは動作します。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

Related 関連記事

ホットタグ

アーカイブ