有一个大脑放屁......是否有可能做出像这样的工作?
template<int a> struct Foo
{
template<int b> struct Bar;
};
template<int a> struct Foo<a>::Bar<1> //Trying to specialize Bar
{
};
我没有有来执行此操作,但它可以让我很好地隐藏命名空间范围内的一些实现细节。
建议赞赏!
P.S。:我忘了提到语言不支持明确专门针对Foo范围内的Bar。无论如何,AFAICS。
答案 0 :(得分:12)
是的,你可以。但是你需要改变调用结构,但只需要一点点。
具体来说,使用策略模式将成员函数的实现重组为一个类(允许IS专门化)。
只要策略类没有嵌套(因此不依赖于非专用模板类型),就允许这样做。
e.g。 (这可能在语法上不正确,但这个想法应该是明确的)
template <class T>
class OuterThingThatIsNotSpecialized
{
template <class U>
void memberWeWantToSpecialize(const U& someObj_)
{
SpecializedStrategy<U>::doStuff(someObj_);
}
};
template <class U>
struct SpecializedStrategy;
template <>
SpecializedStrategy<int>
{
void doStuff(const int&)
{
// int impl
}
};
template <>
SpecializedStrategy<SomeOtherType>
{
void doStuff(const SomeOtherType&)
{
// SOT impl
}
};
这非常有用,因为对没有实现的类型调用OuterThingThatIsNotSpecialized将无法编译。
PS。您甚至可以使用此策略来部分地专门化模板函数,这是C ++不可能实现的。
答案 1 :(得分:11)
1998年标准(ISO14882:1998)第18节第14.7.3节规定,当(外部)模板类未明确专门化时,不允许对(内部)模板成员类进行显式特化。
答案 2 :(得分:3)
根据这些帖子:
http://www.cpptalk.net/template-member-function-specialization-vt11666.html
如果没有专门化外部类,则无法专门化模板类的模板成员。他们不引用经文和章节。我的“C ++编程语言”副本没有立即显示任何内容,我的标准副本在家(我的备份副本,在这里更好地称为“Chris”不在其中: - )
答案 3 :(得分:1)
以下是我一直在做的事情,我认为这更简单/更符合您的尝试:
使用助手
template<int a> struct Foo
{
template<int, int> struct Bar__;
template<int b> using Bar = Bar__<b, b>;
};
template<int a> template<int b, int c> struct Foo<a>::Bar__
{
// general case
const static int x = 0;
};
template<int a> template<int b> struct Foo<a>::Bar__<b, 1>
{
const static int x = 1;
};
int main(int argc, const char * argv[])
{
std::cout << Foo<1>::Bar<0>::x << "\r\n"; // general case - output 0
std::cout << Foo<1>::Bar<1>::x << "\r\n"; // specialized case - output 1
return 0;
}
或者 - 如果您不介意每次加倍专业化,可以删除助手:
没有助手
template<int a> struct Foo
{
template<int b, int c> struct Bar;
};
template<int a> template<int b, int c> struct Foo<a>::Bar
{
// general case
const static int x = 0;
};
template<int a> template<int b> struct Foo<a>::Bar<b, 1>
{
const static int x = 1;
};
int main(int argc, const char * argv[])
{
std::cout << Foo<1>::Bar<0, 0>::x << "\r\n"; // general case - output 0
std::cout << Foo<1>::Bar<1, 1>::x << "\r\n"; // specialized case - output 1
return 0;
}
答案 4 :(得分:0)
你做不到。我尝试了很多变化。然而,这个在GCC 4.1中编译:
template<int a> struct Foo
{
template<int b> struct Bar;
template<1> struct Bar;
};
编辑(审核标准后): 但是,如果给出了a,你可以这样做:
template <> template <> Foo<1> Bar<1>;
但如果Foo不是第一个专门的话,那就不行了。
答案 5 :(得分:0)
正如之前的海报所解释的那样,这是不可能的。但是,您可以将嵌套模板移动到非模板基类中:
struct FooBase
{
template<int b> struct Bar;
}
template<int a> struct Foo : public FooBase
{
};
struct FooBase::Bar<1> // specializing Bar
{
};
答案 6 :(得分:0)
正如其他人所指出的,如果外部类模板也不是专用的,那么C ++不会让你专门化嵌套类。当我遇到这样的情况时,我能够使用隐藏在内部命名空间中的辅助类来解决它:
namespace internal {
template <int a, int b> struct FooBarHelper
{ /* ... */ };
// Specialization
template <int a> struct FooBarHelper<a, 1>
{ /* specialized version goes here */ };
}
template<int a> struct Foo
{
template<int b> struct Bar : public internal::FooBarHelper<a, b>;
};
当然,它并不像你希望的那样隐藏。