2

次のように、2 つの異なるタイプのクラスのメンバー関数テンプレートを特殊化しようとしています。

#include <iostream>
#include <boost/utility/enable_if.hpp>

struct Wibble
{
    static const bool CAN_WIBBLE = true;
};

struct Wobble
{
    static const bool CAN_WIBBLE = false;
};

struct Foo
{
    //template<typename T>   // Why isn't this declaration sufficient?
    //void doStuff();

    template<typename T>
    typename boost::enable_if_c<T::CAN_WIBBLE,void>::type
    doStuff();

    template<typename T>
    typename boost::enable_if_c<!T::CAN_WIBBLE,void>::type
    doStuff();  
};

template<typename T>
typename boost::enable_if_c<T::CAN_WIBBLE,void>::type
Foo::doStuff()
{
    std::cout << "wibble ..." << std::endl;
}

template<typename T>
typename boost::enable_if_c<!T::CAN_WIBBLE,void>::type
Foo::doStuff()
{
    std::cout << "I can't wibble ..." << std::endl;
}

int main()
{
    Foo f;
    f.doStuff<Wibble>();
    f.doStuff<Wobble>();
}

GCC 4.8.2 はコードをコンパイルしますが、VS .NET 2008 はエラー メッセージを吐き出します。

error C2244: 'Foo::doStuff' : unable to match function definition to an existing declaration

        definition
        'boost::enable_if_c<!T::CAN_WIBBLE,void>::type Foo::doStuff(void)'
        existing declarations
        'boost::enable_if_c<!T::CAN_WIBBLE,void>::type Foo::doStuff(void)'
        'boost::enable_if_c<T::CAN_WIBBLE,void>::type Foo::doStuff(void)'
4

2 に答える 2

1

(メンバー) 関数テンプレートを部分的に特化することはできません。話の終わり。

できたとしても、SFINAE に適したプライマリ テンプレートが必要でした。擬似コード:

template<typename T, typename Enable> void doStuff();
template<typename T> void doStuff<T, typename boost::enable_if_c<T::CAN_WIBBLE,void>::type>()
    { std::cout << "wibble ..." << std::endl; }
template<typename T> void doStuff<T, typename boost::enable_if_c<!T::CAN_WIBBLE,void>::type>()
    { std::cout << "I can't wibble ..." << std::endl; }

クラステンプレートの準備ができている場合は、この手法を引き続き使用できます(ファンクターとして、またはテンプレート以外のメソッドを定義する型として...)。

経験則として、関数テンプレートの場合、オーバーロードの解決により、部分的な特殊化の必要性を排除する静的ポリモーフィズムが提供されます。見る

どちらもハーブ・サッター作

于 2014-04-01T21:23:36.943 に答える