読者です 読者をやめる 読者になる 読者になる

enable_ifを書く位置

C++

たまに忘れるのでメモ。


演算子の場合は、戻り値の型をenable_if::typeのように書く。
ここではlazy_enable_ifを使ってますが、戻り値の型がメタ関数の適用結果だからです。

#include <iostream>
#include <string>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/include/push_back.hpp>
#include <boost/fusion/include/is_sequence.hpp>
#include <boost/fusion/include/io.hpp>
#include <boost/utility/enable_if.hpp>

namespace fusion = boost::fusion;

template <class Seq, class T>
typename boost::lazy_enable_if<
    fusion::traits::is_sequence<Seq>,
    fusion::result_of::push_back<const Seq, T>
>::type
    operator+(const Seq& seq, const T& x)
{
    return fusion::push_back(seq, x);
}

int main()
{
    const fusion::vector<int, char> v(1, 'a');
    const std::string s = "Hello";

    std::cout << v + s << std::endl;
}
(1 a Hello)

C++0xの場合はこんなめんどくさいことをせずに関数テンプレートのデフォルトテンプレート引数で。

#include <iostream>
#include <string>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/include/push_back.hpp>
#include <boost/fusion/include/is_sequence.hpp>
#include <boost/fusion/include/io.hpp>
#include <boost/utility/enable_if.hpp>

namespace fusion = boost::fusion;

template <class Seq, class T, class = boost::enable_if<fusion::traits::is_sequence<Seq>>>
typename fusion::result_of::push_back<const Seq, T>::type
    operator+(const Seq& seq, const T& x)
{
    return fusion::push_back(seq, x);
}

int main()
{
    const fusion::vector<int, char> v(1, 'a');
    const std::string s = "Hello";

    std::cout << v + s << std::endl;
}


コンストラクタの場合は戻り値の型がないのでデフォルト引数に書く。

#include <boost/fusion/include/make_vector.hpp>
#include <boost/fusion/include/is_sequence.hpp>
#include <boost/utility/enable_if.hpp>

namespace fusion = boost::fusion;

struct X {
    template <class Seq>
    X(const Seq& seq, typename boost::enable_if<fusion::traits::is_sequence<Seq> >::type* = 0){}
};

int main()
{
    X x(fusion::make_vector(1, 'a', 3.14));
}

C++0xの場合は使わないパラメータを一つ増やすことなどせずに、関数テンプレートのデフォルトテンプレート引数で。

#include <boost/fusion/include/make_vector.hpp>
#include <boost/fusion/include/is_sequence.hpp>
#include <boost/utility/enable_if.hpp>

namespace fusion = boost::fusion;

struct X {
    template <class Seq, class = boost::enable_if<fusion::traits::is_sequence<Seq>>>
    X(const Seq& seq) {}
};

int main()
{
    X x(fusion::make_vector(1, 'a', 3.14));
}

C++0xでは関数テンプレートのデフォルトテンプレート引数一択。