2011-12-15 73 views
5

我有一个模板函数,并希望在编译时确保它没有在特定类的子类型或超类型上实例化。如何创建一个编译时断言模板是特定类型的?

如何违反C++编译器错误?

class base { 
}; 
class derived : public base { 
}; 
class lowest : public derived { 
}; 

template <typename T> 
bool isCorrect(const T& obj) { 
    typedef foo<T> D; 
    foo<T> *def = foo<T>::find(); 
    return (def && def->getAnswer(object)); 
} 

我想isCorrect只可用于derived类,但不baselowest。请注意,可能有许多其他最低类和一系列要排除的基类以及可接受的替代派生类。

在C++中有一种方法来限制模板只适用于我明确指定的派生类吗?

+0

可能重复的[模板约束C++](http://stackoverflow.com/questions/122316/template-constraints-c ) – 2011-12-15 00:48:46

+0

具体而言,这可能很有用:http://www.boost.org/doc/libs/1_48_0/libs/concept_check/concept_check.htm – 2011-12-15 00:50:58

+0

为什么你不写重载? – GManNickG 2011-12-15 01:51:22

回答

4

这是我所知道的一种技术。

首先,创建另一个模板类policy_enforcer。声明该类没有定义它,并且还提供了它的专门用于derived这也被定义

template<typename T> struct policy_enforcer; 
template<> struct policy_enforcer<derived> { }; 

然后,在函数内部要锁定下来,包括表达sizeof(policy_enforcer<T>)。由于sizeof上的不完整类型是编译错误,所以这会阻止编译代码。

更新与现场代码:using baseusing derivedusing lowest

9

类型性状,特别是is_base_of

#include <type_traits> 

template <typename T> 
bool isCorrect(const T& obj) { 
    static bool const is_base = std::is_base_of<base, T>::value; 
    static bool const derives = std::is_base_of<derived, T>::value; 
    // specify allowed types here 
    static bool const is_derived = std::is_same<T, derived>::value; 
    // --- 
    static_assert((!is_base && !derives) || is_derived, "wrong argument type"); 

    typedef foo<T> D; 
    foo<T> *def = foo<T>::find(); 
    return (def && def->getAnswer(object)); 
} 

请注意,这是C++ 11特有的,但您可以通过Boost.TypeTraits获得相同的行为。

1

您可以使用模板专业化。

只能为您想要使用的类型实施isCorrect

对于其他类型,您可以实现虚拟方法,例如返回false,或根本不实现isCorrect,在这种情况下,它不会编译为其他类型。

#include <iostream> 

using namespace std; 

class base { 
}; 
class derived : public base { 
}; 
class lowest : public derived { 
}; 

// using this it will fail if you try to pass anything 
// else than `derived` 
// template <typename T> 
//  bool isCorrect(const T& obj); 

template <typename T> 
bool isCorrect(const T& obj) { 
    cout << __PRETTY_FUNCTION__ << endl; 
    return false; 
} 

template <> 
bool isCorrect<derived>(const derived& obj) { 
    cout << __PRETTY_FUNCTION__ << endl; 
    return true; 
// typedef foo<derived> D; 
// foo<derived> *def = foo<derived>::find(); 
// return (def && def->getAnswer(object)); 
} 

测试:

int main() 
{ 
    base b; 
    derived d; 
    lowest l; 

    cout << isCorrect(b) << endl; 
    cout << isCorrect(d) << endl; 
    cout << isCorrect(l) << endl; 
} 

输出:

bool isCorrect(const T&) [with T = base] 
0 
bool isCorrect(const T&) [with T = derived] 
1 
bool isCorrect(const T&) [with T = lowest] 
0 
相关问题