Question: It is a bit strange. I am trying to write a code which detects whether a type is a string object. The char \* or other object types should lead to false not true. The following code gives me: 

> 
> error: template parameters not deducible in partial specialization:
> 
> 
> 

I do not understand what the message means. Even searched online, I cannot figure out how to fix this:

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

template <typename T>
struct is_string : std::false_type { };

template <typename T>
struct is_string<std::string> : std::true_type<T> { };

class Temp
{
  int a;
};

int main()
{
    // Expect: false
    std::cout << is_string<int>::value << std::endl;
    std::cout << is_string<char *>::value << std::endl;
    std::cout << is_string<Temp>::value << std::endl;

    // Expect: true
    std::cout << is_string<std::string>::value << std::endl;
    std::cout << is_string<const std::string>::value << std::endl;
    std::cout << is_string<std::string&>::value << std::endl;
}

```

If there is a out of box `std` tool, that's welcome

Answer: 
The template specialization should look like this:

```
template <>
struct is_string<std::string> : std::true_type { };

```

But even if you use it, your template will return `false` for cv-qualified `string` or references to it.

> 
> I did not use `std::is_same` because it rejects types such as `const string` or `string &` as string.
> 
> 
> 

The right way to do it is `std::is_same_v<std::remove_cv_t<std::remove_reference_t<`**`your_type`**`>>, std::string>` (or using `std::decay_t`, as the other answer suggests).

Or, in C++20: `std::is_same_v<std::remove_cvref_t<<`**`your_type`**`>, std::string>`.
The specialization should not include `typename T`, so:

```
template <>
struct is_string<std::string> : std::true_type<T> { };

```

Since you want `const std::string` and `std::string&` and combinations thereof to count as `string` too, you may find it easier to inherit from `integral_constant` instead (which is what `false_type` and `true_type` does).

Example:

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

template <typename T>
struct is_string : std::integral_constant<bool,
                                         std::is_same_v<std::string, std::decay_t<T>>> {};

// helper
template<typename T>
inline constexpr bool is_string_v = is_string<T>::value;

```