2

I have the following template for checking if a type is std::string or not. It compiles fine on GCC, but fails on Clang. Which is the correct behavior? Is there a way to make it work on both?

#include<iostream>
#include<string>
#include<type_traits>

using namespace std;

template <typename T> //Checks if T is string type, by testing for the existence of member type "traits_type"
class is_string
{
public:
    template<typename C> std::false_type test(...);
    template<typename C> std::true_type test(decltype(sizeof(typename C::traits_type)));

    enum {
    value = decltype(((is_string<T>*)nullptr) -> test<T>( sizeof(0) ))::value
    };
};

int main() {
cout<<is_string<string>::value<<endl;
}

Error on Clang:

trial.cpp:15:51: error: member access into incomplete type 'is_string<std::basic_string<char> >'
    value = decltype(((is_string<T>*)nullptr) -> test<T>( sizeof(0) ))::value
                                              ^
trial.cpp:20:7: note: in instantiation of template class 'is_string<std::basic_string<char> >' requested here
cout<<is_string<string>::value<<endl;
      ^
trial.cpp:8:7: note: definition of 'is_string<std::basic_string<char> >' is not complete until the closing '}'
class is_string
SPMP
  • 1,181
  • 1
  • 9
  • 24

2 Answers2

5

Clang is correct, because, as it says, the type is incomplete until it is finished being defined. I imagine that if you turn on -pedantic then you'll get errors in gcc also.

A simpler way to do what you want is to just use std::is_same:

#include <string>
#include <type_traits>

static_assert(std::is_same<std::string, std::string>::value, "");
static_assert(not std::is_same<std::string, int>::value, "");
Chris Beck
  • 15,614
  • 4
  • 51
  • 87
  • I do have other templates which do similar things, but is not as simple as using ``is_same ``. What should I be doing in such cases? – SPMP Mar 08 '16 at 19:15
  • @user2308211: It depends on exactly what you are doing, but often you can (1) just use SFINAE to enable / disable code as appropriate and don't use a trait, or (2) look at the templates `std::enable_if`, also `void_t`: http://stackoverflow.com/questions/27687389/how-does-void-t-work – Chris Beck Mar 08 '16 at 19:38
  • In case it's useful to someone, I finally went with ``template `` ``using is_string = std::is_same;`` – SPMP Mar 08 '16 at 20:51
0

The question of whether g++ is right or clang is right is already answered by @ChrisBeck.

You can simplify your implementation to:

template <typename T>
struct is_string
{
   static bool const value = std::is_same<std::string, T>::value;
};
Community
  • 1
  • 1
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • I do need similar templates for other purposes. In general, check if a class has a particular member. How can I do that correctly? – SPMP Mar 08 '16 at 19:30
  • @user2308211, it will be better to ask that in a different question. – R Sahu Mar 08 '16 at 19:30