C++ template specialization without default function

后端 未结 5 1628
轻奢々
轻奢々 2021-02-01 02:49

I have the following code that compiles and works well:

template
T GetGlobal(const char *name);

template<>
int GetGlobal(cons         


        
相关标签:
5条回答
  • 2021-02-01 03:06

    I would suggest not to actually provide an implementation, just a bare declaration of the method.

    The other option would be to use a compile-time assert. Boost has a number of such beasts.

    namespace mpl = boost::mpl;
    BOOST_MPL_ASSERT((mpl::or_< boost::same_type<T, double>,
                                boost::same_type<T, int> >));
    

    There is also its message version counterpart, which would help.

    0 讨论(0)
  • 2021-02-01 03:12

    Though it is an old and outdated question, it may worth noting that C++11 had solved this issue using deleted functions:

    template<typename T>
    T GetGlobal(const char *name) = delete;
    
    template<>
    int GetGlobal<int>(const char *name);
    

    UPDATE

    This will not compile under MacOS llvm 8. It is due to a still hanging 4 years old defect (see this bug report).

    The following workaround will fit the issue (using a static_assert construct).

    template<typename T>
    T GetGlobal(const char *name) {
        static_assert(sizeof(T) == 0, "Only specializations of GetGlobal can be used");
    }
    
    template<>
    int GetGlobal<int>(const char *name);
    

    UPDATE

    Visual studio 15.9 has the same bug. Use the previous workaround for it.

    0 讨论(0)
  • 2021-02-01 03:23

    The following are alternative techniques to using boost:

    Declare a typedef to a dependent name

    This works because name lookup for DONT only occurs when 'T' has been replaced. This is a similar (but legal) version of the example given by Kirill

    template <typename T>
    T GetGlobal (const char * name) {
        typedef typename T::DONT CALL_THIS_FUNCTION;
    }
    

    Use an incomplete return type

    This technique doesn't work for specializations, but it will work for overloads. The idea is that its legal to declare a function which returns an incomplete type, but not to call it:

    template <typename T>
    class DONT_CALL_THIS_FUNCTION GetGlobal (const char * name);
    
    0 讨论(0)
  • 2021-02-01 03:25

    If you don't implement it, you'll at least get a linker error. If you want a compile-time error, you could do this with class templates:

    template<typename T>
    struct GlobalGetter;
    
    template<>
    struct GlobalGetter<int> {
      static int GetGlobal(const char *name);
    };
    
    template<>
    struct GlobalGetter<double> {
      static double GetGlobal(const char *name);
    };
    
    template<typename T>
    T GetGlobal(const char *name)
    {
      return GlobalGetter<T>::GetGlobal(name);
    }
    
    0 讨论(0)
  • 2021-02-01 03:29

    To get a compile-time error implement it as:

    template<typename T>
    T GetGlobal(const char *name) { T::unimplemented_function; }
    // `unimplemented_function` identifier should be undefined
    

    If you use Boost you could make it more elegant:

    template<typename T>
    T GetGlobal(const char *name) { BOOST_STATIC_ASSERT(sizeof(T) == 0); }
    

    C++ Standard guarantees that there is no such type which has sizeof equal to 0, so you'll get a compile-time error.

    As sbi suggested in his comments the last could be reduced to:

    template<typename T>
    T GetGlobal(const char *name) { char X[!sizeof(T)]; }
    

    I prefer the first solution, because it gives more clear error message (at least in Visual C++) than the others.

    0 讨论(0)
提交回复
热议问题