Попробуйте
<?php
$to = "somebody@example.com, somebodyelse@example.com";
$subject = "HTML email";
$message = "
<html>
<head>
<title>HTML email</title>
</head>
<body>
<p>This email contains HTML Tags!</p>
<table>
<tr>
<th>Firstname</th>
<th>Lastname</th>
</tr>
<tr>
<td>John</td>
<td>Doe</td>
</tr>
</table>
</body>
</html>";
// Always set content-type when sending HTML email
$headers = "MIME-Version: 1.0" . "\r\n";
$headers .= "Content-type:text/html;charset=UTF-8" . "\r\n";
// More headers
$headers .= 'From: <webmaster@example.com>' . "\r\n";
$headers .= 'Cc: myboss@example.com' . "\r\n";
mail($to,$subject,$message,$headers);
?>
Добавить в файл cpp:
constexpr char foo::baz[];
Причина: вы должны указать определение статического члена, а также объявление. Объявление и инициализатор входят в определение класса, но определение члена должно быть отдельным.
Не является более элегантным решением изменить char[]
на:
static constexpr char * baz = "quz";
Таким образом, мы можем иметь определение / объявление / инициализатор в 1 строке кода.
char[]
вы можете использовать sizeof
, чтобы получить длину строки во время компиляции, при этом char *
вы не можете (в этом случае он будет возвращать ширину типа указателя, 1).
– gnzlbg
10 May 2016 в 10:52
Это действительно недостаток в C ++ 11, как объяснили другие, в C ++ 11 статическая переменная-член constexpr, в отличие от любой другой глобальной переменной constexpr, имеет внешнюю связь, поэтому она должна быть явно определена где-то.
Также стоит отметить, что вы часто можете избежать со статическими переменными-членами constexpr без определений при компиляции с оптимизацией, так как они могут оказаться вложенными во все виды использования, но если вы легко компилируете без оптимизации, ваша программа не будет связываться. Это делает эту очень распространенную скрытую ловушку - ваша программа отлично компилируется с оптимизацией, но как только вы отключите оптимизацию (возможно, для отладки), она не может связываться.
Хорошая новость: этот недостаток исправлен в C ++ 17! Этот подход немного запутан, хотя: в C ++ 17 статические константные переменные-члены-константы неявно встроены . Наличие inline, применяемого к переменным , является новой концепцией в C ++ 17, но это фактически означает, что в любом месте они не нуждаются в явном определении.
C ++ 17 исправляет эту проблему для константных переменных-членов constexpr, требующих определения вне строки, если она была использована ord. См. Первоначальный ответ ниже для деталей pre C ++ 17.
Предложение P0386 Inline Variables вводит возможность применения спецификатора inline к переменным. В частности, для этого случая constexpr подразумевает inline для статических переменных-членов. В предложении говорится:
Встроенный спецификатор может применяться как к переменным, так и к функциям. Переменная, объявленная inline, имеет ту же семантику, что и функция, объявленная inline: она может быть определена идентично в нескольких единицах перевода, должна определяться в каждой единицы перевода, в которой она одурена, а поведение программы выглядит так, как будто ровно одна переменная.
и изменено [basic.def] p2:
Объявление является определением, если ...
- it объявляет статический элемент данных вне определения класса, и переменная была определена внутри класса с помощью спецификатора constexpr (это использование устарело, см. [des.static_constexpr]),
...
и добавьте [des.static_constexpr] :
Для совместимости с предыдущими стандартами C ++, статический элемент данных constexpr может быть избыточно обновляется вне класса без инициализатора. Это использование устарело. [Пример:
struct A { static constexpr int n = 5; // definition (declaration in C++ 2014) }; constexpr int A::n; // redundant declaration (definition in C++ 2014)
- конец примера]
Оригинальный ответ
В C ++ 03 нам разрешалось предоставлять только в классе intializers для const-интегралов или const перечисления типов , в C ++ 11 с использованием constexpr это было расширено до типов литералов .
В C ++ 11 нам не нужно предоставлять определение области пространства имен для статического члена constexpr, если это не odr-used , мы можем видеть это из черновика Стандартная секция C ++ 11
9.4.2
[class.static.data] , в которой говорится ( акцент мой вперед ):[ ...] Статический член данных типа literal может быть объявлен в определении класса с помощью спецификатора constexpr; если это так, в его декларации указывается логический или равный-инициализатор, в котором каждое предложение-инициализатор, являющееся выражением-присваиванием, является постоянным выражением. [Примечание. В обоих случаях член может отображаться в постоянных выражениях. -End note] Элемент все еще должен быть определен в области пространства имен, если он используется в odr (3.2) в программе, а определение области пространства имен не должно содержать инициализатор.
Итак, тогда вопрос будет, есть
baz
odr-used здесь:std::string str(baz);
, а ответ да , и поэтому нам нужна область пространства имен определение.
Итак, как мы определяем, является ли переменная odr-used ? В исходной формулировке C ++ 11 в разделе
3.2
[basic.def.odr] говорится:Выражение потенциально оценивается, если оно не является неоцененным операндом ( Пункт 5) или его подвыражение. Переменная, имя которой отображается как потенциально оцениваемое выражение, используется odr, если оно не является объектом, удовлетворяющим требованиям для появления в постоянном выражении (5.19), и немедленно применяется преобразование lvalue-to-rval (4.1).
Таким образом,
baz
дает константное выражение , но преобразование lvalue-to-rvalue не применяется сразу, поскольку оно неприменимо из-за кbaz
, являющемуся массивом. Это описано в разделе4.1
[conv.lval] , в котором говорится:Значение gl (3.10) нефункционного типа без массива T может преобразуется в prvalue.53 [...]
Что применяется в преобразовании преобразования в массив .
Это формулировка [basic.def.odr] была изменена из-за отчета о дефектах 712 , поскольку некоторые случаи не были охвачены этой формулировкой, но эти изменения не изменяют результаты для этого случая .
constexpr
не имеет к этому никакого отношения? (baz
- постоянное выражение)
– M.M
4 March 2015 в 05:23
integral or enumeration type
, но в остальном, да, важно, что это выражение константа i>.
– Shafik Yaghmour
4 March 2015 в 05:35
constexpr
- это еще одна, не имеющая отношения вещь, не связанная непосредственно с привязкой. – Kerrek SB 15 August 2014 в 13:21