简体   繁体   English

在模板实例化中限制参数类型

[英]Restrict parameter type in template instantiation

I'm trying to trigger a compile time error if the user of my library tries to instantiate a template with a type that is not appropriate. 如果我的库的用户尝试使用不合适的类型实例化模板,我试图触发编译时错误。 I've implemented: 我实施了:

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

template <>
struct good_type<string> { enum { value = true }; };

template <>
struct good_type<int64_t> { enum { value = true }; };

template <typename T>
struct X
{
  BOOST_STATIC_ASSERT(good_type<T>::value);
};

int main(int argc, char** argv)
{
  X<string> x1; 
  X<int64_t> x2;
  X<float> x3; 
  return 0;
}

which works, but the message I get from gcc is a bit surprising: 这是有效的,但我从gcc得到的消息有点令人惊讶:

error: invalid application of 'sizeof' to incomplete type 'boost::STATIC_ASSERTION_FAILURE<false>' 

Should I be using a different Boost macro? 我应该使用不同的Boost宏吗? Is there a better way to do this? 有一个更好的方法吗?

Thanks! 谢谢!

You can use boost::enable_if , along with typelist. 您可以使用boost::enable_if以及typelist。

Define a typelist which contains all the types which you want to support, and write some metafunction(s), to check if a given type exists in the list or not, and then pass the value which metafunction returns to enable_if , so as to enable/disable the class. 定义一个包含所有要支持的类型的类型列表 ,并编写一些元函数,检查列表中是否存在给定类型 ,然后将元函数返回的值传递给enable_if ,以便启用/禁用该类。


Alright, I wrote a code for demo. 好吧,我写了一个演示代码。 Its not using boost::enable_if though (that is for you to experiment with). 它虽然没有使用boost::enable_if (你可以boost::enable_if )。

Here is the framework first: 首先是框架:

////////////////////////////////////////////////////////////
//framework

struct null_type {};

template<typename H, typename  T=null_type>
struct typelist
{
   typedef H Head;
   typedef T Tail;
};

template<typename T, typename TList> struct exists;

template<typename T, typename Tail> 
struct exists<T, typelist<T, Tail> >
{
    static const bool value = true;
};

template<typename T, typename Head, typename Tail> 
struct exists<T, typelist<Head, Tail> >
{
    static const bool value = false || exists<T, Tail>::value;
};

template<typename T> 
struct exists<T, null_type >
{
    static const bool value = false;
};

template<bool>
struct compile_time_error;

template<>
struct compile_time_error<true> {};

-- -

Now follows the testing code: 现在遵循测试代码:

//////////////////////////////////////////////////////////////
//usage

typedef typelist<int> t1;
typedef typelist<short, t1> t2;
typedef typelist<char, t2> t3;
typedef typelist<unsigned char, t3> t4;

typedef t4 supported_types;//supported_types: int, short, char, unsigned char

template<typename T>
struct X
{
    compile_time_error<exists<T,supported_types>::value> unsupported_type_used;
};

int main() {

 //testing if exists<> work or not!
 cout <<(exists<int,supported_types>::value)<< endl;        //should print 1
 cout <<(exists<unsigned int,supported_types>::value)<<endl;//should print 0
 cout <<(exists<char,supported_types>::value)<< endl;       //should print 1
 cout <<(exists<long,supported_types>::value)<< endl;       //should print 0

 X<int> x1;   //okay - int is supported!
 //X<long> x2;  //error - long is unsupported! 
 return 0;
}

which compiles perfectly fine ( ideone ), and gives this output (for the cout statements): 编译完全正常( ideone ),并给出此输出(对于cout语句):

1
0
1
0

But if you uncomment the line X<long> x2; 但如果你取消注释X<long> x2; in the above code, it will not compile, since long is an unsupported type. 在上面的代码中,它不会编译,因为long是不受支持的类型。 And it gives this error, which is easy to read and understand ( ideone ): 它给出了这个错误,易于阅读和理解( ideone ):

prog.cpp: In instantiation of 'X': prog.cpp:在'X'的实例化中:
prog.cpp:68: instantiated from here prog.cpp:68:从这里实例化
prog.cpp:56: error: 'X::unsupported_type_used' has incomplete type prog.cpp:56:错误:'X :: unsupported_type_used'的类型不完整
prog.cpp:38: error: declaration of 'struct compile_time_error' prog.cpp:38:错误:'struct compile_time_error'的声明

Hope this helps you. 希望这对你有所帮助。


Now you can write a class template called enable_if_supported which takes two type arguments: T and supported_types . 现在您可以编写一个名为enable_if_supported的类模板,它带有两个类型参数: Tsupported_types You can derive your class from enable_if_supported as: 您可以从enable_if_supported派生您的类:

template<typename T>
struct X : enable_if_supported<T, supported_types>
{
   //your code
};

This looks a bit clean. 这看起来有点干净。 enable_if_supported class template now is defined in the framework section. 现在, enable_if_supported类模板在框架部分中定义。 See it here working : http://www.ideone.com/EuOgc 请在此处查看: http//www.ideone.com/EuOgc

How about this : 这个怎么样 :

#include <string>

template <typename T>
struct good_type;

template <>
struct good_type< std::string > {};

template <>
struct good_type< int > {};

template < typename T >
struct X
{
  good_type< T > someVar;
};

int main(int argc, char** argv)
{
  X< std::string > x1;
  X< int > x2;
  X<float> x3;
}

produces : 产生:

main.cpp: In instantiation of ‘X<float>’:
main.cpp:22:12:   instantiated from here
main.cpp:15:18: error: ‘X<T>::someVar’ has incomplete type
main.cpp:4:8: error: declaration of ‘struct good_type<float>’

One more way : 还有一种方法:

#include <string>

template <typename T>
struct good_type;

template <> struct good_type< std::string > {typedef char value;};
template <> struct good_type< int > {typedef char value;};

template < typename T >
struct X
{
  typedef typename good_type< T >::value valid;
};

int main(int argc, char** argv)
{
  X< std::string > x1;
  X< int > x2;
  X<float> x3;
}

will produce : 将产生:

main.cpp: In instantiation of ‘X<float>’:
main.cpp:19:12:   instantiated from here
main.cpp:12:42: error: invalid use of incomplete type ‘struct good_type<float>’
main.cpp:4:8: error: declaration of ‘struct good_type<float>’

and you can create a macro to define valid types : 并且您可以创建一个宏来定义有效类型:

#define VALID( x ) template <> struct good_type< x > {typedef char value;}

VALID( std::string );
VALID( int );

BOOST_MPL_ASSERT produces better messages: http://ideone.com/BR0GJ BOOST_MPL_ASSERT产生更好的消息: httpBOOST_MPL_ASSERT

prog.cpp: In instantiation of ‘X<float>’:
prog.cpp:24:   instantiated from here
prog.cpp:17: error: no matching function for call to 
  ‘assertion_failed(mpl_::failed************ good_type<float>::************)’
prog.cpp: In function ‘int main(int, char**)’:
prog.cpp:22: warning: unused variable ‘x1’
prog.cpp:23: warning: unused variable ‘x2’
prog.cpp:24: warning: unused variable ‘x3’

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM