如何在不更改类模板的情况下为模板类的模板方法添加第二种类型?

时间:2017-07-10 22:48:26

标签: c++ templates

我有一个模板类

template <typename S>
class Foo {

   template <typename T>
   T Bar();

}

如何更改Bar以便我可以在不更改类模板类型的情况下使用它?

Foo<int> f;
f.Bar<int,MyType>();

这里,int是Foo的类型,MyType只是在其实例类型之上更改Bar()行为的另一种类型。

这不按预期工作:

template <typename S>
template <typename T>
T Foo<S>::Bar()
{
    // logic with T t
}

但这有效:

template <typename S>
template <typename T>
T Foo<S>::Bar(T * dummyNullPointer)
{
    // logic with T t
}

是否有一个整洁的版本而不是代码?

f.Bar<int>((float *)0);

最好

f.Bar<int,MyType>();

f.Bar<MyType>(); // better, but expects int for example and gives error

编辑:实际使用情况

void SomeClass<SomeType>::SomeMethod(SomeType1<SomeType> p)
{
      Something something = p.SomeWork<Something>(); // does not work
}

2 个答案:

答案 0 :(得分:1)

您不能专门化非专业类的成员函数。这只是一种语言限制。

如果您准备专攻课程,可以这样做:

#include <iostream>
#include <tuple>

template <typename S>
struct Foo {

    template <typename T>
    T Bar();

};

template <typename S>
template <typename T>
T Foo<S>::Bar()
{
    std::cout << "usual thing" << std::endl;
    return T();
}

struct MyType {};

template<> template<>
std::tuple<int, MyType> Foo<int>::Bar<std::tuple<int, MyType>>()
{
    std::cout << "my thing" << std::endl;
    return std::tuple<int, MyType> { 1, {} };
};


int main()
{
    auto f = Foo<int>();
    auto x = f.Bar<int>();
    auto y = f.Bar<std::tuple<int, MyType>>();
}

如果没有,那么你必须让你的成员函数遵从可以部分专业化的函数对象:

#include <iostream>
#include <tuple>


// general case
template<class S, class T, class...Ts>
struct BarOp;

template <typename S>
struct Foo {

    template <typename...Ts>
    auto Bar() -> decltype(auto)
    {
        auto op = BarOp<Foo<S>, Ts...>();
        return op(this);
    }

};

// general case of single T
template<class S, class T>
struct BarOp<S, T>
{
    auto operator()(S* p) const
    {
        std::cout << "usual thing" << std::endl;
        return T();
    }
};


struct MyType {};

// now partially specialise for T, MyTyoe
template<class S, class T>
struct BarOp<S, T, MyType>
{
    auto operator()(S* p) const
    {
        std::cout << "other thing" << std::endl;
        return T(10);
    }
};

int main()
{
    auto f = Foo<int>();
    auto x = f.Bar<int>();
    auto y = f.Bar<int, MyType>();
}

预期产出:

usual thing
other thing

答案 1 :(得分:0)

编辑:可以运行:

#include <iostream>

template <typename S>
class Foo {
   /* internal use of S */
   int bar2(S s);
public:
   template <typename T, typename K>
   T Bar() {
        /* internal use of K, may be also S */
        K var = 5.3;
        return (T) var; //convert K to T
   }
};


int main() {
    Foo<int> f;
    int res = f.Bar<int, double>();
    std::cout <<"res = " << res << std::endl;

    return 0;
}