C++ 如何避免为每个成员函数重复类模板规范?

C++ 如何避免为每个成员函数重复类模板规范?,c++,templates,C++,Templates,如果我有这样的模板类规范 template <typename T> class MyClass { public: void fun1(); // ... void funN(); }; template <typename T> void MyClass<T>::fun1() { // definition } // ... template <typename T> void MyClass<T&g

如果我有这样的模板类规范

template <typename T>
class MyClass {
public:
    void fun1();
    // ...
    void funN();
};

template <typename T>
void MyClass<T>::fun1() {
    // definition
}

// ...

template <typename T>
void MyClass<T>::funN() {
    // definition
}
模板
类MyClass{
公众:
void fun1();
// ...
void funN();
};
模板
void MyClass::fun1(){
//定义
}
// ...
模板
void MyClass::funN(){
//定义
}
如果我将类模板更改为其他内容,则假设我添加了一个额外的参数:

template <typename T, typename U>
class MyClass {
    // ...
};
模板
类MyClass{
// ...
};
然后我必须更改每个函数定义(fun1,…,funN)以符合类模板规范:

template <typename T, typename U>
void MyClass<T,U>::fun1() { //... }
模板
void MyClass::fun1(){/…}
有没有避免这种情况的策略?我可以使用宏吗

#define DFLT_TEMPLATE template<typename T, typename U>
#define DFLT_CLASS  class<T,U>

DFLT_TEMPLATE
void DFLT_CLASS::fun1() { // ... }
#定义DFLT#U模板
#定义DFLT_类
DFLT_模板
void DFLT_类::fun1(){/…}

或者这被认为是不好的做法?

是的,您可以,但不要忘记在文件末尾使用“#undef DFLT_TEMPLATE”和“#undef DFLT_CLASS”以避免编译器警告。如果您的项目有多个具有相同宏定义的模板,那么对我来说,在这里使用宏的好处远远被缺点所掩盖。是的,如果使用宏,那么如果需要添加其他模板参数,只需进行一次修改。但是任何其他阅读你的代码的人都可能会呕吐


我的意思是,你会对你所有的模板都这样做吗?你的代码会被丑陋的宏所侵扰。

我会认为这种方法很差。你抱怨的是你已经改变了你的设计(你需要一个额外的模板参数),现在想要一个乱七八糟的东西来节省打字


引入宏会降低代码的可读性。预处理器定义当然有自己的位置,但就个人而言,我从不提倡预处理器定义,因为我懒得修改我的函数。

继承比宏好

如果您只想更改少数函数和变量,请使专用类继承一个提供公共函数/变量的公共类。

可能有一些(或多或少不好的)解决方法,但您肯定指出了C++的一个“缺失”特性:
类命名空间扩展

有些人已经提出用这种方式扩展C++:

--
使用宏不是一个好主意(关于宏的常见事情…)。 在最坏的情况下,我更愿意在这种情况下内联编写函数成员定义,或者更好地使用编辑器来帮助您轻松更新类定义

宏是不好的,因为它们允许您在应该编写程序的地方编写代码编辑函数。 如果要编辑代码,请使用编辑器(sed、M-x replace-*、Find&replace…)

您有多少成员函数认为这是一个问题

我认为,要么它们足够小,可以在类模板中定义,要么将它们的算法调整为一个额外的模板参数将远远超过替换这些函数头


而且,你的编辑应该马上为你做这件事

尽可能将函数定义放在类模板定义中。它是一个模板,所以除非您使用Comeau编译器,否则它们不会在不同的TU中关闭

如果函数使用在类定义和函数定义之间定义的某个对象,那么您可以使用一些技巧使该对象依赖于模板参数,即使“实际上”它不是。例如:

template <typename T>
struct Foo {
    void usebar();
};

struct Bar {
    int a; 
    Foo<int> circularity; // circular dependency between Foo and Bar
    Bar() : a(3) {}
};

template <typename T> void Foo<T>::usebar() {
    Bar b;
    std::cout << b.a << "\n";
}
模板
结构Foo{
void usebar();
};
结构条{
INTA;
Foo循环;//Foo和Bar之间的循环依赖关系
Bar():a(3){}
};
模板void Foo::usebar(){
b栏;

std::cout+1和你按下按钮时我输入的内容差不多。:)不要在意别人说什么。如果你真的讨厌多次重写东西(比如我)-然后只使用宏。我知道使用宏的所有缺点和陷阱。但是我仍然更喜欢宏,而不是复制+粘贴等。根据我个人的经验,重写东西,除了道德败坏之外,比使用宏危险得多。有一个干净的解决方案:只需将所有定义放在类定义中utsourcing,我认为调用外部定义的函数也可以:提供一个模板版本,让人们根据自己的意愿为自定义类型重载它。毕竟,这就是
Boost
hash\u value
所做的,例如,这就是我们已经用于
交换的。
template <typename T>
struct Foo {
    void usebar();
};

struct Bar {
    int a; 
    Foo<int> circularity; // circular dependency between Foo and Bar
    Bar() : a(3) {}
};

template <typename T> void Foo<T>::usebar() {
    Bar b;
    std::cout << b.a << "\n";
}
// we only have to write "same" once
template <typename T, typename U>
struct same {
    typedef U type;
};

struct Bar;

template <typename T>
struct Foo {
    void usebar() {
        typename same<T,Bar>::type b;
        std::cout << b.a << "\n";
    }
};

struct Bar {
    int a; 
    Foo<int> circularity; // circularity gone
    Bar() : a(3) {} 
};
struct Bar;

template <typename T, typename B = Bar>
struct Foo {
    void usebar() {
        B b;
        std::cout << b.a << "\n";
    }
};

struct Bar {
    int a;
    Foo<int> circularity;
    Bar() : a(3) {}
};
int main() {
    Foo<int> f;
    f.usebar();
}