2017-01-06 18 views
14

Załóżmy, że mam jakąś klasę:Czy mogę szablonować zdefiniowane przez użytkownika literały?

template <typename T> 
class Foo { 
    const T* x_; 
public: 
    Foo(const T* str) : x_{str} {} 
}; 

i podać kilka zdefiniowanych przez użytkownika literały, które tworzą Foo obiektu:

Foo<char> operator"" _foo(const char* str, std::size_t) { 
    return Foo<char>{str}; 
} 

Foo<wchar_t> operator"" _foo(const wchar_t* str, std::size_t) { 
    return Foo<wchar_t>{str}; 
} 

// etc. for char16_t and char32_t. 

Moje pytanie jest takie: dlaczego nie mogę szablon nich i zapisać konieczności przepisać kod?

template <typename T> 
Foo<T> operator"" _foo(const T* str, std::size_t) { 
    return Foo<T>{str}; 
} 

gcc 5.4.0 (Ubuntu 5.4.0-6ubuntu1 ~ 16.04.4) oraz 7.0.0 (skompilowany siebie) Sprawozdanie

wiadomość
error: ‘Foo<T> operator""_foo(const T*, std::size_t)’ has invalid argument list 
Foo<T> operator"" _foo(const T* str, std::size_t) { 
               ^

Błąd wydaje się być na tyle jasne, ale Nie widzę powodu, dla którego nie wolno mi było zasadniczo tego robić; więc czy robię to niepoprawnie, czy jest to naprawdę zabronione?

+0

2.14.8/3 sugestia szablon literały operatora zdefiniowane przez użytkownika są ważne. Per/5, Twój kod wydaje mi się prawidłowy. Twój kompilator nie zbiera specjalizacji szablonu operatora jako (konkretnie) zdefiniowanego przez użytkownika _string_ literal operatora, a mój szablon fu nie jest wystarczająco dobry, aby dowiedzieć się, czy jest to błąd, czy konsekwencja reguł wyszukiwania. –

+0

@LightnessRacesinOrbit Domyślam się, że [over.literal] jest bardziej odpowiedni. Wygląda na to, że szablon funkcji, który zawiera literalny identyfikator operatora, musi być zgodny ze stałą deklaracją (mniej więcej "szablon podwójny operator" "_x()"). Żadna inna forma nie jest dozwolona. – skypjack

+1

@skypjack: Sformułowanie sprawia, że ​​sugeruję wypróbowanie go z jawną instancją. –

Odpowiedz

11

Rozważmy this:

If the literal operator is a template, it must have an empty parameter list and can have only one template parameter, which must be a non-type template parameter pack with element type char

Innymi słowy, deklaracja dosłownym szablonu operatora powinno być:

template <char...> double operator "" _x(); 

To nie twoja sprawa.


Nie jestem prawnikiem języka, ale myślę, że ten odcinek standardzie, które są istotne dla sprawa jest [over.literal] (Link do projektu roboczego).

Fragment [over.literal]/2 następująco:

A function template declared with a literal-operator-id is a literal operator template.

Poniżej [over.literal]/5 cytowany:

The declaration of a literal operator template shall have an empty parameter-declaration-clause and its template-parameter-list shall have a single template-parameter that is a non-type template parameter pack ([temp.variadic]) with element type char.

Wydaje mi się, że deklaracje podobne do tego w pytaniu są wyraźnie zabronione przez normy.
Bardziej ogólnie, szablon funkcji, który deklaruje operator dosłowny, musi ściśle przestrzegać określonego wzorca.


am I doing this incorrectly, or is this genuinely not allowed?

Powiedziałbym, że to autentycznie niedozwolone.

W każdym razie, można nadal korzystać z funkcji szablonu, jeśli masz złożonej logiki, że nie chcesz, aby powtórzyć w każdej operatora:

template<typename T> 
Foo<T> create(const T *str) { 
    // your logic... 
    return Foo<T>{str}; 
} 

Foo<char> operator"" _foo(const char *str, std::size_t) { 
    return create(str); 
} 

Foo<wchar_t> operator"" _foo(const wchar_t *str, std::size_t) { 
    return create(str); 
} 

jest to kwestia dodatkową warstwę zadnie i to wszystko.
Oczywiście, nie warto, jeśli wszyscy operatorzy są jednym organem liniowym.

+2

Myślę, że to wystarczająco jasne. Zastanawiam się, dlaczego na to nie pozwolili. Być może przyszłe standardy złagodzą ten zakaz ... – Zorawar

+1

@Zorawar Jestem po prostu ciekawy jak ty, ale nie rozumiem, dlaczego nie jest to dozwolone. Przepraszam. – skypjack

+1

W porządku! Dziękuję za odpowiedź. Przynajmniej wiem, że nie popełniłem głupiego błędu! – Zorawar

Powiązane problemy