如何防止非专业模板实例化?

ere*_*eOn 38 c++ templates boost compilation

我有一个模板化class(称之为Foo),它有几个特化.如果有人试图使用非专业版本,我希望编译失败Foo.

这是我实际拥有的:

template <typename Type>
class Foo
{
  Foo() { cannot_instantiate_an_unspecialized_Foo(); }

  // This method is NEVER defined to prevent linking.
  // Its name was chosen to provide a clear explanation why the compilation failed.
  void cannot_instantiate_an_unspecialized_Foo();
};

template <>
class Foo<int>
{    };

template <>
class Foo<double>
{    };
Run Code Online (Sandbox Code Playgroud)

以便:

int main()
{
  Foo<int> foo;
}
Run Code Online (Sandbox Code Playgroud)

适用时:

int main()
{
  Foo<char> foo;
}
Run Code Online (Sandbox Code Playgroud)

才不是.

显然,编译器链只在链接过程发生时才会抱怨.但有没有办法让它在之前抱怨?

我可以用boost.

Seb*_*fel 43

只是不要定义类:

template <typename Type>
class Foo;

template <>
class Foo<int> { };

int main(int argc, char *argv[]) 
{
    Foo<int> f; // Fine, Foo<int> exists
    Foo<char> fc; // Error, incomplete type
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

为什么这样做?仅仅因为没有任何通用模板.声明,是的,但没有定义.

  • 这是一个错误的决定,因为错误将在链接阶段而不是编译时发出。而且您将永远不知道确切地在哪里使用了非专业类。 (2认同)

Ker*_* SB 22

无法定义基本情况:

template <typename> class Foo;             // no definition!

template <> class Foo<int> { /* ... */ };  // Foo<int> is OK
Run Code Online (Sandbox Code Playgroud)

  • 我不敢相信我错过了......谢谢.接受Schnommus答案是因为他声誉较低.赞成这一点是为了公平. (8认同)

Luc*_*ton 17

C++ 0x的一个技巧(也可用于C++ 03 static_assert仿真,但错误消息不一定比保留主模板未定义更好):

template<typename T>
struct dependent_false: std::false_type {};

template<typename Type>
struct Foo {
    static_assert( dependent_false<Type>::value
                 , "Only specializations of Foo may be used" );
};
Run Code Online (Sandbox Code Playgroud)

断言仅在Foo使用主模板实例化时触发.使用static_assert( false, ... )会一直触发断言.

  • 类似的技巧需要更少的类型是使用static_assert(sizeof(Type)== 0,"..."); 作为替代方案,您可以使用BOOST_STATIC_ASSERT.我个人更喜欢那些,因为上面的"不定义基本模板"可能会导致链接器错误,当你只使用引用/指针.通常你应该停下片刻并重新考虑一下你是否真的需要这个,因为模板是通用的,你在这里限制 (2认同)
  • @mako 这意味着总是错误的。如果您在某处定义了“Foo&lt;int&gt;”显式专业化,那么它不应该包含这个特定的断言。因此,当实例化“那个”特化时,不会触发任何断言——主模板与显式或部分特化无关。 (2认同)
  • @mako 是的。`static_assert( false );` 总是会触发。如果您有兴趣更深入地研究这一点,您可能需要寻找依赖类型和表达式(“dependent_false”的名字当然来自其中)。 (2认同)