具有多个模板参数的C ++单模板特化

时间:2010-09-22 11:46:47

标签: c++ templates specialization

喂!

我想只专注于两种模板类型中的一种。例如。 template <typename A, typename B> class X应该针对单个函数X<float, sometype>::someFunc()进行特殊实现。

示例代码:

main.h:

#include <iostream>

template <typename F, typename I>
class B
{
public:
    void someFunc()
    {
        std::cout << "normal" << std::endl;
    };

    void someFuncNotSpecial()
    {
        std::cout << "normal" << std::endl;
    };
};

template <typename I>
void B<float, I>::someFunc();

main.cpp中:

#include <iostream>
#include "main.h"

using namespace std;

template <typename I>
void B<float, I>::someFunc()
{
    cout << "special" << endl;
}

int main(int argc, char *argv[])
{
    B<int, int> b1;
    b1.someFunc();
    b1.someFuncNotSpecial();

    B<float, int> b2;
    b2.someFunc();
    b2.someFuncNotSpecial();
}

class B的编译失败。这是不是真的,这在C ++中是不可能的?什么是最好的解决方法?

[编辑]

template <float, typename I> void B<float, I>::someFunc();导致 main.h:26:错误:'float'不是模板常量参数的有效类型

template <typename I> void B<float, I>::someFunc();导致 main.h:27:错误:无效使用不完整类型'B类'

我正在使用gcc。

[编辑]

我不想专门研究整个班级,因为还有其他功能没有专业化。

4 个答案:

答案 0 :(得分:18)

您必须提供类模板B部分特化

template <typename I>
class B<float, I>
{
public:
    void someFunc();
};

template <typename I>
void B<float, I>::someFunc()
{
    ...
}

您也可以在专业化中定义someFunc

然而,如果你只想专门化一个函数,而不是一个类做。克。

template <typename F, typename I>
void someFunc(F f, I i) { someFuncImpl::act(f, i); }

template <typename F, typename I>
struct someFuncImpl { static void act(F f, I i) { ... } };

// Partial specialization
template <typename I>
struct someFuncImpl<float, I> { static void act(float f, I i) { ... } };

但如果没有这个技巧,你就无法专门化一个功能模板。

答案 1 :(得分:5)

  

虽然你可以完全专注   类模板的成员函数,   你不能_partially专门化   成员职能。    - Andrei Alexandrescu

部分 Class 专业化由其他海报解释。

但是,您可以使用重载:

template <class T, class U> T fun(U obj); // primary template
template <class U> void Fun<void, U>(U obj); // illegal pertial
// specialization
template <class T> T fun (Window obj); // legal (overloading)

如果你想深入研究这个问题,你可以在A. Alexandrescu的“现代C ++设计”中深入阅读这个问题。

答案 2 :(得分:0)

解决方案1.将所有实现移动到像B_Base这样的基类。然后专注于float来覆盖someFunc。如下所示

    template <typename F, typename I>
    class B : B_Base<F, I>
    {
    }

    template <typename I>
    class B<float, I> : B_Base<flat, I>
    {
    public:
        void someFunc() {....}
    };

解决方案2.使用函数重载,将float作为输入或boost :: is_same调度。不幸的是,你的函数 someFunc 没有参数。所以它需要改变界面。

答案 3 :(得分:0)

我认为 C++ 专家 Mayer 为我们提供了一个优雅的功能。缺点是它取决于 GCC 功能。

#include <map>
#include <iostream>
#include <string>

using namespace std;


template<typename... T>
void TemplatePrint(T... args) {
    std::cout << __PRETTY_FUNCTION__ << std::endl;
}


int main()
{
    map<string, int> arr={{"1", 1}, {"2", 2}, {"3", 3}};
    auto itr = arr.find("3");
    TemplatePrint<decltype(itr)>(itr);


    return 0;
}

GCC 会打印出迭代器的真实 decltype(真实的),即:

void TemplatePrint(T ...) [with T = {std::_Rb_tree_iterator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> >}]
相关问题