我正在尝试编写一个类模板,其中方法签名会根据模板参数而改变。我的目标是尽可能少地复制代码。考虑这个例子,首先是类声明:
// a.hxx
#ifndef A_HXX
#define A_HXX
template<typename T>
struct A
{
void foo(T value) const;
void bar() const;
};
#include <string>
#ifndef short_declaration
template<>
struct A<std::string>
{
void foo(const std::string &value) const;
void bar() const;
};
#else // short_declaration
template<>
struct A<std::string>
{
void foo(const std::string &value) const;
};
#endif // short_declaration
#endif // A_HXX
现在是类定义:
// a_impl.hxx
#ifndef A_IMPL_HXX
#define A_IMPL_HXX
#include "a.hxx"
#include <iostream>
#include <typeinfo>
template<typename T>
void A<T>::foo(T value) const
{
std::cout << "A<T=" << typeid(T).name() << ">::foo(" << value << ")"
<< std::endl;
}
template<typename T>
void A<T>::bar() const
{
std::cout << "A<T=" << typeid(T).name() << ">::bar()" << std::endl;
}
void A<std::string>::foo(const std::string &value) const
{
std::cout << "A<std::string>::foo(" << value << ")" << std::endl;
}
#ifndef skip_duplicates
void A<std::string>::bar() const
{
std::cout << "A<std::string>::bar()" << std::endl;
}
#endif // skip_duplicates
#endif // A_IMPL_HXX
现在是一个测试程序:
// test.cxx
//#define skip_duplicates
//#define short_declaration
#include "a_impl.hxx"
int main(void)
{
A<int> obj1;
A<std::string> obj2;
int value1(1);
std::string value2("baz");
obj1.foo(value1);
obj1.bar();
obj2.foo(value2);
obj2.bar();
return 0;
}
如果像这样编译,我得到(对于我的typeid实现)的预期输出:
A<T=i>::foo(1)
A<T=i>::bar()
A<std::string>::foo(baz)
A<std::string>::bar()
但我当然希望在我的示例中启用skip_duplicates
甚至short_declaration
。有点similar question,ecatmur回复说需要给出完整的类,所以至少定义short_declaration
是行不通的。
其他人如何处理使用可能将大对象作为参数的方法创建类模板的问题?
答案 0 :(得分:2)
您可以将重复项提取到基类中:
template<typename T>
struct Base{
void Bar()
{
std::cout << "A<T=" << typeid(T).name() << ">::bar()" << std::endl;
}
protected:
~Base(){}
template<typename U>
void DoFoo(U value)
{
std::cout << "A<T=" << typeid(T).name() << ">::foo(" << value << ")"
<< std::endl;
}
};
template<typename T>
struct A : Base<T> {
void Foo(T value)
{
DoFoo(value);
}
};
template<>
struct A<std::string> : Base<std::string> {
void Foo(const std::string& value)
{
DoFoo(value);
}
};
答案 1 :(得分:0)
根据hansmaad的答案和Yakk的评论,我认为以下是我将采用的解决方案:
// a.hxx
#ifndef A_HXX
#define A_HXX
template<typename T, typename U=T>
struct Abase
{
void foo(U value) const;
void bar() const;
};
template<typename T>
struct A : Abase<T> { };
#include <string>
template<>
struct A<std::string> : Abase<std::string, const std::string &> { };
#endif // A_HXX
这个实施:
// a_impl.hxx
#ifndef A_IMPL_HXX
#define A_IMPL_HXX
#include "a.hxx"
#include <iostream>
#include <typeinfo>
template<typename T, typename U>
void Abase<T, U>::foo(U value) const
{
std::cout << "A<T=" << typeid(T).name() << ",U=" << typeid(U).name()
<< ">::foo(" << value << "): &value=" << int(&value) << std::endl;
}
template<typename T, typename U>
void Abase<T, U>::bar() const
{
std::cout << "A<T=" << typeid(T).name() << ",U=" << typeid(U).name()
<< ">::bar()" << std::endl;
}
#endif // A_IMPL_HXX
测试程序可以保持原样或获得其他类似的行:
//...
std::cout << "&value=" << int(&value1) << std::endl;
//...
std::cout << "&value=" << int(&value2) << std::endl;
//...
感谢您的回答和建议!