Matt
Matt

Reputation: 7160

Literal class with std::string only works with template specialization?

The following definition is not allowed by my compiler as std::string has a non trivial destructor (makes sense that teststr can't have a trivial dtor when a member doesn't):

class teststr
{
private:
    std::string _m;
public:
    constexpr teststr(std::string value) : _m(value) {};

    constexpr std::string m() const { return _m; }
    void m(std::string value) { _m = value; }
};

However, the following equivalent (to the best of my knowledge) definition of teststr is allowed:

template<typename T>
class test
{
private:
    T _m;
public:
    constexpr test(T value) : _m(value) {};

    constexpr T m() const { return _m; }
    void m(T value) { _m = value; }
};

typedef test<std::string> teststr;

What is it about templating the type that makes this definition allowed?

Upvotes: 5

Views: 122

Answers (1)

user743382
user743382

Reputation:

constexpr is more often allowed in templates because it is not generally known at template definition time whether the member satisfies the requirements of constexpr. When a template member is declared constexpr, it is determined at template instantiation time whether constexpr is appropriate, and if not, it is silently dropped.

Given

template <typename T> struct test {
  T val;
  constexpr test(T val) : val(val) { }
};

you can have

constexpr test<int> i = 3;

because with T = int, the constructor meets the requirements of constexpr, but you cannot have

constexpr test<string> s = "";

because that constructor does not meet the requirements of constexpr.

It is not a hard error to instantiate test<string> because that would severely limit the ability to use constexpr in templates.

From the standard (C++11):

7.1.5 The constexpr specifier [dcl.constexpr]

6 If the instantiated template specialization of a constexpr function template or member function of a class template would fail to satisfy the requirements for a constexpr function or constexpr constructor, that specialization is not a constexpr function or constexpr constructor. [...]

Upvotes: 5

Related Questions