2017-08-15 56 views
6

我正在它有一个模板功能使项目失败编译:使C++模板函数的具体实例

template <class T> 
T foo<T>(T val) { return someFunc(val); } 

template <> 
bool foo<bool>(bool val) { return otherFunc(val); }; 

现在,我有一个类Bar,我不想接受为输入。事实上,我想让它产生一个容易发现的编译错误。问题是,如果我这样做:

template <> 
Bar foo<Bar>(Bar val) { static_assert(false,"uh oh..."); } 

它在每次编译时失败。我发现https://stackoverflow.com/a/3926854/7673414,它说我需要引用模板类型,否则静态断言总是会发生。问题是我在这里没有模板类型。如果我这样做:

template< typename T > 
struct always_false { 
    enum { value = false }; 
}; 

template <> 
Bar foo<Bar>(Bar val) { static_assert(always_false<Bar>::value,"uh oh..."); } 

那么它也总是编译失败。有没有办法确保类型为Bar的模板实例化总是会导致编译错误?

回答

18

由于foo是一个完整的专业化,它总是会被编译,静态断言总是会被调用。

然而,有一个easier way

template <> 
Bar foo<Bar>(Bar val) = delete; 

这会说这个特定的版本将被删除,而且不能被调用。

+0

这很好,但我会删除d-tor,而不必删除所有各种c-tor。 –

+1

@YehezkelB。这是一个函数模板,而不是一个类模板。您可以删除函数模板特化,而不仅仅是构造函数和析构函数。 –

2

您可以使用std::is_same来满足您的要求。

template <class T> 
T foo<T>(T val) 
{ 
    // Make sure T is not Bar 
    static_assert(std::is_same<T, Bar>::value == false, "uh oh..."); 
    return someFunc(val); 
} 
+1

请您添加缺少')''为static_assert'? –

+0

@风王,完成。感谢您指出。 –

3

另一种方法是使模板(不专业版),只有当类型是不同的,从Bar

template <class T> 
typename std::enable_if< ! std::is_same<T, Bar>::value, T>::type foo<T>(T val) 
{ return someFunc(val); } 

如果你可以使用C++ 14时,可以使用简化std::enable_if_t

template <class T> 
std::enable_if_t< ! std::is_same<T, Bar>::value, T> foo<T>(T val) 
{ return someFunc(val); } 
1

如果您使用的是C++ 17,您可以将所有内容放在一起:constexpr if

template< typename T > 
auto foo(T val) 
{ 
    static_assert(!std::is_same_v<T,Bar>); 

    if constexpr(std::is_same_v<T,bool>) 
    { 
     return other_func(val); 
    } 
    else 
    { 
     return some_func(val); 
    } 

} 

然后你可以在static_assert的第一行,没有模板特定实例编译失败的痛苦。

一个活生生的例子,请https://wandbox.org/permlink/PpR6G0gcvMRoxhhZ